/**
* Tests for SVG sanitization
*
* NOTE: These tests require browser APIs (DOMParser, XMLSerializer) and must be run
* in a browser environment. To run these tests:
*
* 1. Using deno-web-test:
* deno run -A packages/deno-web-test/cli.ts packages/ui/src/v2/components/ct-svg/sanitize-svg.test.ts
*
* 2. Or run them manually in a browser console
*
* These tests will fail in a standard Deno test environment because DOMParser
* is not available outside of a browser context.
*/
import { assert } from "@std/assert";
import { sanitizeSvg } from "./sanitize-svg.ts";
// Helper to check if string contains substring
function contains(str: string, substring: string): boolean {
return str.indexOf(substring) !== -1;
}
// Helper to check if string does NOT contain substring
function notContains(str: string, substring: string): boolean {
return str.indexOf(substring) === -1;
}
// Valid SVG tests
Deno.test("sanitizeSvg: should pass through simple valid SVG", function () {
const svg = '';
const result = sanitizeSvg(svg);
assert(contains(result, "';
const result = sanitizeSvg(svg);
assert(notContains(result, "onclick"), "Should not contain onclick");
assert(notContains(result, "alert"), "Should not contain alert");
assert(contains(result, "';
const result = sanitizeSvg(svg);
assert(notContains(result, "onload"), "Should not contain onload");
assert(notContains(result, "alert"), "Should not contain alert");
assert(contains(result, "';
const result = sanitizeSvg(svg);
assert(notContains(result, "onerror"), "Should not contain onerror");
assert(notContains(result, "alert"), "Should not contain alert");
assert(contains(result, "';
const result = sanitizeSvg(svg);
// Event handlers should be removed regardless of case
assert(
notContains(result.toLowerCase(), "onclick"),
"Should not contain onclick",
);
assert(
notContains(result.toLowerCase(), "onload"),
"Should not contain onload",
);
assert(notContains(result, "alert"), "Should not contain alert");
});
// URL sanitization tests
Deno.test("sanitizeSvg: should remove javascript: URL in href", function () {
const svg =
'';
const result = sanitizeSvg(svg);
assert(notContains(result, "javascript:"), "Should not contain javascript:");
assert(notContains(result, "alert"), "Should not contain alert");
assert(contains(result, "click';
const result = sanitizeSvg(svg);
assert(notContains(result, "javascript:"), "Should not contain javascript:");
assert(notContains(result, "alert"), "Should not contain alert");
assert(contains(result, "click";
const result = sanitizeSvg(svg);
assert(notContains(result, "vbscript:"), "Should not contain vbscript:");
assert(notContains(result, "msgbox"), "Should not contain msgbox");
assert(contains(result, "alert('xss')\">click";
const result = sanitizeSvg(svg);
// The key security requirement: dangerous URL protocol is removed
assert(
notContains(result, "data:text/html"),
"Should not contain data:text/html",
);
// Also verify the XSS payload doesn't get through
assert(notContains(result, "alert"), "Should not contain alert");
});
Deno.test("sanitizeSvg: should preserve safe URLs", function () {
const svg =
'';
const result = sanitizeSvg(svg);
assert(
contains(result, "https://example.com"),
"Should contain https://example.com",
);
assert(contains(result, "click";
const result = sanitizeSvg(svg);
assert(
notContains(result.toLowerCase(), "javascript:"),
"Should not contain javascript:",
);
assert(notContains(result, "alert"), "Should not contain alert");
});
// Dangerous element removal tests
Deno.test("sanitizeSvg: should remove foreignObject element", function () {
const svg =
'';
const result = sanitizeSvg(svg);
assert(
notContains(result, "foreignObject"),
"Should not contain foreignObject",
);
assert(notContains(result, "';
const result = sanitizeSvg(svg);
assert(notContains(result, "';
const result = sanitizeSvg(svg);
assert(notContains(result, "';
const result = sanitizeSvg(svg);
assert(notContains(result, "onclick"), "Should not contain onclick");
assert(notContains(result, "alert"), "Should not contain alert");
assert(contains(result, "");
assert(result === "", "Should return empty string");
});
Deno.test("sanitizeSvg: should handle non-SVG content", function () {
const result = sanitizeSvg("
not svg
");
// Note: DOMParser with "image/svg+xml" may parse non-SVG elements differently depending on the browser
// The important thing is that the result is safe (no scripts, no event handlers)
// and non-SVG elements like
are either removed or made safe
// The current implementation allows
since it's not in the dangerous elements list
// This is acceptable since
without event handlers is not a security risk
assert(
typeof result === "string" && result.length >= 0,
"Should return a string",
);
});
// Style element tests
Deno.test("sanitizeSvg: should preserve style elements", function () {
const svg =
'';
const result = sanitizeSvg(svg);
// Note: The implementation does NOT remove