From c2c2b4aaa84c67d2eccd4ef4f94b5ea444a7f73a Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 6 Jan 2026 21:54:47 +0100 Subject: [PATCH] fix(core): sanitize sensitive attributes on SVG script elements This commit updates the DOM security schema and sanitization logic to properly recognize and sanitize `href` and `xlink:href` attributes on SVG ` + + \`, + }) + export class TestCmp { + attr = './script.js'; + } + `, + ); + + env.driveMain(); + + const jsContents = env.getContents('test.js'); + expect(jsContents).toContain( + 'i0.ɵɵattribute("href", ctx.attr, i0.ɵɵsanitizeResourceUrl, "xlink")("href", ctx.attr, i0.ɵɵsanitizeResourceUrl);', + ); + }); + it('should not generate sanitizers for URL properties in hostBindings fn in Component', () => { env.write( `test.ts`, diff --git a/packages/compiler/src/schema/dom_security_schema.ts b/packages/compiler/src/schema/dom_security_schema.ts index c938c5c70e1..dfe5618dd53 100644 --- a/packages/compiler/src/schema/dom_security_schema.ts +++ b/packages/compiler/src/schema/dom_security_schema.ts @@ -134,6 +134,10 @@ export function SECURITY_SCHEMA(): {[k: string]: SecurityContext} { 'object|codebase', 'object|data', 'script|src', + // The below two are for Script SVG + // See: https://developer.mozilla.org/en-US/docs/Web/API/SVGScriptElement/href + 'script|href', + 'script|xlink:href', ]); // Keep this in sync with SECURITY_SENSITIVE_ELEMENTS in packages/core/src/sanitization/sanitization.ts diff --git a/packages/core/src/sanitization/sanitization.ts b/packages/core/src/sanitization/sanitization.ts index 86edae0803b..0b2c65ce167 100644 --- a/packages/core/src/sanitization/sanitization.ts +++ b/packages/core/src/sanitization/sanitization.ts @@ -213,6 +213,10 @@ export function ɵɵtrustConstantResourceUrl(url: TemplateStringsArray): Trusted return trustedScriptURLFromString(url[0]); } +// Define sets outside the function for O(1) lookups and memory efficiency +const SRC_RESOURCE_TAGS = new Set(['embed', 'frame', 'iframe', 'media', 'script']); +const HREF_RESOURCE_TAGS = new Set(['base', 'link', 'script']); + /** * Detects which sanitizer to use for URL property, based on tag name and prop name. * @@ -221,18 +225,12 @@ export function ɵɵtrustConstantResourceUrl(url: TemplateStringsArray): Trusted * If tag and prop names don't match Resource URL schema, use URL sanitizer. */ export function getUrlSanitizer(tag: string, prop: string) { - if ( - (prop === 'src' && - (tag === 'embed' || - tag === 'frame' || - tag === 'iframe' || - tag === 'media' || - tag === 'script')) || - (prop === 'href' && (tag === 'base' || tag === 'link')) - ) { - return ɵɵsanitizeResourceUrl; - } - return ɵɵsanitizeUrl; + const isResource = + (prop === 'src' && SRC_RESOURCE_TAGS.has(tag)) || + (prop === 'href' && HREF_RESOURCE_TAGS.has(tag)) || + (prop === 'xlink:href' && tag === 'script'); + + return isResource ? ɵɵsanitizeResourceUrl : ɵɵsanitizeUrl; } /** diff --git a/packages/core/test/bundling/router/bundle.golden_symbols.json b/packages/core/test/bundling/router/bundle.golden_symbols.json index 73422b015a5..0e672a6c835 100644 --- a/packages/core/test/bundling/router/bundle.golden_symbols.json +++ b/packages/core/test/bundling/router/bundle.golden_symbols.json @@ -115,6 +115,7 @@ "HOST", "HOST_ATTR", "HOST_TAG_NAME", + "HREF_RESOURCE_TAGS", "HYDRATION", "HistoryStateManager", "HostAttributeToken", @@ -274,6 +275,7 @@ "SIGNAL", "SIGNAL_NODE", "SIMPLE_CHANGES_STORE", + "SRC_RESOURCE_TAGS", "SVG_NAMESPACE", "SafeSubscriber", "SafeValueImpl",