diff --git a/packages/compiler/src/render3/view/i18n/meta.ts b/packages/compiler/src/render3/view/i18n/meta.ts index 8029f72c00f2..8b0cd8c5bfe3 100644 --- a/packages/compiler/src/render3/view/i18n/meta.ts +++ b/packages/compiler/src/render3/view/i18n/meta.ts @@ -208,7 +208,7 @@ export class I18nMetaVisitor implements html.Visitor { isTrustedType = isTrustedTypesSink(node.name, name); } - if (isTrustedType || name.toLowerCase().startsWith('on')) { + if (isTrustedType || isPossibleEventHandler(name)) { this._reportError( attr, `Translating attribute '${name}' is disallowed for security reasons.`, @@ -350,3 +350,14 @@ export function i18nMetaToJSDoc(meta: I18nMeta): o.JSDocComment { } return o.jsDocComment(tags); } + +/** + * Check if the propertyName is a potential event handler. + * We consider a property to be a potential event handler if its name is longer than 2 characters and starts with 'on' (e.g. 'onclick', 'onload', etc.). + * @param propertyName The name of the property to check. + * @returns True if the property is a potential event handler, false otherwise. + */ +function isPossibleEventHandler(propertyName: string): boolean { + const name = propertyName.toLowerCase(); + return name.length > 2 && name !== 'only' && name.startsWith('on'); +} diff --git a/packages/core/test/linker/security_integration_spec.ts b/packages/core/test/linker/security_integration_spec.ts index 5e351acbbc2e..6ed339d2a865 100644 --- a/packages/core/test/linker/security_integration_spec.ts +++ b/packages/core/test/linker/security_integration_spec.ts @@ -385,6 +385,13 @@ describe('security integration tests', function () { ); }); + it('should not throw error on translating "on" attribute', () => { + const template = `
`; + TestBed.overrideComponent(SecuredComponent, {set: {template}}); + + expect(() => TestBed.createComponent(SecuredComponent)).not.toThrow(); + }); + it('should throw error on security-sensitive attributes with constant values', () => { const template = ``; TestBed.overrideComponent(SecuredComponent, {set: {template}});