From 00a7f6f9b970121f5b73bf790b86ba49bf11ab0e Mon Sep 17 00:00:00 2001 From: SkyZeroZx <73321943+SkyZeroZx@users.noreply.github.com> Date: Sun, 7 Jun 2026 19:16:53 -0500 Subject: [PATCH] fix(core): sanitize anchor protocol bindings Treat `protocol` property bindings on `` and `` as URL contexts. This prevents a sanitized `href` from being re-schemed into an executable `javascript:` URL by a later protocol property write. --- .../src/schema/dom_security_schema.ts | 4 +- .../dom_element_schema_registry_spec.ts | 3 + .../src/sanitization/dom_security_schema.ts | 4 +- .../core/test/acceptance/security_spec.ts | 63 +++++++++++++++++++ 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/packages/compiler/src/schema/dom_security_schema.ts b/packages/compiler/src/schema/dom_security_schema.ts index 1acc4ede7df7..72e0360a850a 100644 --- a/packages/compiler/src/schema/dom_security_schema.ts +++ b/packages/compiler/src/schema/dom_security_schema.ts @@ -59,8 +59,8 @@ export function SECURITY_SCHEMA(): {[k: string]: SecurityContext} { // NB: no SCRIPT contexts here, they are never allowed due to the parser stripping them. registerContext(SecurityContext.URL, /** Namespace */ undefined, [ ['*', ['formAction']], - ['area', ['href']], - ['a', ['href', 'xlink:href']], + ['area', ['href', 'protocol']], + ['a', ['href', 'xlink:href', 'protocol']], ['form', ['action']], // The below two items are safe and should be removed but they require a G3 clean-up as a small number of tests fail. diff --git a/packages/compiler/test/schema/dom_element_schema_registry_spec.ts b/packages/compiler/test/schema/dom_element_schema_registry_spec.ts index 839a206c5082..cc02dc237c75 100644 --- a/packages/compiler/test/schema/dom_element_schema_registry_spec.ts +++ b/packages/compiler/test/schema/dom_element_schema_registry_spec.ts @@ -152,7 +152,10 @@ If 'onAnything' is a directive input, make sure the directive is imported by the expect(registry.securityContext('iframe', 'srcdoc', false)).toBe(SecurityContext.HTML); expect(registry.securityContext('p', 'innerHTML', false)).toBe(SecurityContext.HTML); expect(registry.securityContext('a', 'href', false)).toBe(SecurityContext.URL); + expect(registry.securityContext('a', 'protocol', false)).toBe(SecurityContext.URL); expect(registry.securityContext('a', 'style', false)).toBe(SecurityContext.STYLE); + expect(registry.securityContext('area', 'href', false)).toBe(SecurityContext.URL); + expect(registry.securityContext('area', 'protocol', false)).toBe(SecurityContext.URL); expect(registry.securityContext('base', 'href', false)).toBe(SecurityContext.RESOURCE_URL); // SVG animate and set attributes diff --git a/packages/core/src/sanitization/dom_security_schema.ts b/packages/core/src/sanitization/dom_security_schema.ts index 1acc4ede7df7..72e0360a850a 100644 --- a/packages/core/src/sanitization/dom_security_schema.ts +++ b/packages/core/src/sanitization/dom_security_schema.ts @@ -59,8 +59,8 @@ export function SECURITY_SCHEMA(): {[k: string]: SecurityContext} { // NB: no SCRIPT contexts here, they are never allowed due to the parser stripping them. registerContext(SecurityContext.URL, /** Namespace */ undefined, [ ['*', ['formAction']], - ['area', ['href']], - ['a', ['href', 'xlink:href']], + ['area', ['href', 'protocol']], + ['a', ['href', 'xlink:href', 'protocol']], ['form', ['action']], // The below two items are safe and should be removed but they require a G3 clean-up as a small number of tests fail. diff --git a/packages/core/test/acceptance/security_spec.ts b/packages/core/test/acceptance/security_spec.ts index 5035c85f55cc..0483b0035bcc 100644 --- a/packages/core/test/acceptance/security_spec.ts +++ b/packages/core/test/acceptance/security_spec.ts @@ -933,6 +933,69 @@ describe('SVG