diff --git a/packages/compiler/src/schema/trusted_types_sinks.ts b/packages/compiler/src/schema/trusted_types_sinks.ts index 0d69ccee47f9..bd8fe1f66197 100644 --- a/packages/compiler/src/schema/trusted_types_sinks.ts +++ b/packages/compiler/src/schema/trusted_types_sinks.ts @@ -24,8 +24,11 @@ const TRUSTED_TYPES_SINKS = new Set([ // NB: no TrustedScript here, as the corresponding tags are stripped by the compiler. // TrustedScriptURL + 'base|href', 'embed|src', + 'frame|src', 'iframe|src', + 'link|href', 'object|codebase', 'object|data', ]); diff --git a/packages/compiler/test/schema/trusted_types_sinks_spec.ts b/packages/compiler/test/schema/trusted_types_sinks_spec.ts index dca36afa89ab..fabef073a6a4 100644 --- a/packages/compiler/test/schema/trusted_types_sinks_spec.ts +++ b/packages/compiler/test/schema/trusted_types_sinks_spec.ts @@ -12,10 +12,12 @@ describe('isTrustedTypesSink', () => { it('should classify Trusted Types sinks', () => { expect(isTrustedTypesSink('iframe', 'srcdoc')).toBeTrue(); expect(isTrustedTypesSink('p', 'innerHTML')).toBeTrue(); + expect(isTrustedTypesSink('base', 'href')).toBeTrue(); expect(isTrustedTypesSink('embed', 'src')).toBeTrue(); + expect(isTrustedTypesSink('frame', 'src')).toBeTrue(); expect(isTrustedTypesSink('iframe', 'src')).toBeTrue(); + expect(isTrustedTypesSink('link', 'href')).toBeTrue(); expect(isTrustedTypesSink('a', 'href')).toBeFalse(); - expect(isTrustedTypesSink('base', 'href')).toBeFalse(); expect(isTrustedTypesSink('div', 'style')).toBeFalse(); }); diff --git a/packages/core/test/linker/security_integration_spec.ts b/packages/core/test/linker/security_integration_spec.ts index 49b88b56cd0e..bc1357260846 100644 --- a/packages/core/test/linker/security_integration_spec.ts +++ b/packages/core/test/linker/security_integration_spec.ts @@ -6,9 +6,9 @@ * found in the LICENSE file at https://angular.dev/license */ -import {DomSanitizer} from '@angular/platform-browser'; -import {clearTranslations, loadTranslations} from '@angular/localize'; import {computeMsgId} from '@angular/compiler'; +import {clearTranslations, loadTranslations} from '@angular/localize'; +import {DomSanitizer} from '@angular/platform-browser'; import { ChangeDetectionStrategy, Component, @@ -376,6 +376,15 @@ describe('security integration tests', function () { expect(link.getAttribute('href')).toEqual('unsafe:javascript:alert(1)'); }); + it('should throw on translated base href attributes', () => { + const template = ``; + TestBed.overrideComponent(SecuredComponent, {set: {template}}); + + expect(() => TestBed.createComponent(SecuredComponent)).toThrowError( + /Translating attribute 'href' is disallowed for security reasons./, + ); + }); + it('should throw error on security-sensitive attributes with constant values', () => { const template = ``; TestBed.overrideComponent(SecuredComponent, {set: {template}});