From 5f3333ad4f1174df868c673e59821089ef6c7856 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Thu, 11 Jun 2026 08:21:14 +0000 Subject: [PATCH] fix(compiler): restrict possible event handler check to property names longer than 2 characters Previously, the compiler disallowed translation of any attribute starting with 'on' for security reasons. This incorrectly disallowed translation of the 'on' attribute itself, which is not an event handler. This commit introduces `isPossibleEventHandler` to verify that the property name has a length greater than 2 in addition to starting with 'on'. This allows attributes like 'on' to be translated while still correctly disallowing actual event handlers like 'onerror', 'onclick', etc. --- packages/compiler/src/render3/view/i18n/meta.ts | 13 ++++++++++++- .../core/test/linker/security_integration_spec.ts | 7 +++++++ 2 files changed, 19 insertions(+), 1 deletion(-) 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}});