Skip to content

fix(zone.js): harden zoneSymbolEventNames against __proto__ key (defense-in-depth)#69233

Open
arturovt wants to merge 1 commit into
angular:mainfrom
arturovt:fix/zone.js_proto_DoS
Open

fix(zone.js): harden zoneSymbolEventNames against __proto__ key (defense-in-depth)#69233
arturovt wants to merge 1 commit into
angular:mainfrom
arturovt:fix/zone.js_proto_DoS

Conversation

@arturovt
Copy link
Copy Markdown
Contributor

@arturovt arturovt commented Jun 8, 2026

Initialize zoneSymbolEventNames with Object.create(null) instead of {}.

This is hardening only. addEventListener('proto', fn) is not
directly attacker-controllable — its presence in an application is
itself an application bug and a prerequisite for any issue here.

Without this change, if that application bug exists, two unexpected
behaviors follow depending on environment:

Browser: zoneSymbolEventNames['proto'] reads the proto getter
and returns Object.prototype (truthy), bypassing prepareEventNames.
symbolEventName resolves to undefined and window['undefined'] = []
throws TypeError.

Node.js + --disable-proto=throw: the assignment
zoneSymbolEventNames['proto'] = {} inside prepareEventNames
triggers the disabled proto setter and throws.

Using Object.create(null) removes the proto accessor from the
map so the key is treated as a plain missing property in both cases.

@pullapprove pullapprove Bot requested a review from atscott June 8, 2026 16:57
@angular-robot angular-robot Bot added the area: zones Issues related to zone.js label Jun 8, 2026
@ngbot ngbot Bot added this to the Backlog milestone Jun 8, 2026
@atscott
Copy link
Copy Markdown
Contributor

atscott commented Jun 8, 2026

Please update the commit message to indicate this is hardening only. addEventListener('proto', fn) is not directly something that an attacker would be able to do without some other issue in the application. addEventListener('proto', fn) already existing in the app is an application bug.

…nse-in-depth)

Initialize zoneSymbolEventNames with Object.create(null) instead of {}.

This is hardening only. addEventListener('__proto__', fn) is not
directly attacker-controllable — its presence in an application is
itself an application bug and a prerequisite for any issue here.

Without this change, if that application bug exists, two unexpected
behaviors follow depending on environment:

Browser: zoneSymbolEventNames['__proto__'] reads the __proto__ getter
and returns Object.prototype (truthy), bypassing prepareEventNames.
symbolEventName resolves to undefined and window['undefined'] = []
throws TypeError.

Node.js + --disable-proto=throw: the assignment
zoneSymbolEventNames['__proto__'] = {} inside prepareEventNames
triggers the disabled __proto__ setter and throws.

Using Object.create(null) removes the __proto__ accessor from the
map so the key is treated as a plain missing property in both cases.
@arturovt arturovt force-pushed the fix/zone.js_proto_DoS branch from 17679bc to 4787cc1 Compare June 8, 2026 17:05
@arturovt arturovt changed the title fix(zone.js): __proto__ event name causes DoS in browser and Node.js fix(zone.js): harden zoneSymbolEventNames against __proto__ key (defense-in-depth) Jun 8, 2026
@arturovt
Copy link
Copy Markdown
Contributor Author

arturovt commented Jun 8, 2026

Please update the commit message to indicate this is hardening only. addEventListener('proto', fn) is not directly something that an attacker would be able to do without some other issue in the application. addEventListener('proto', fn) already existing in the app is an application bug.

Done.

@atscott atscott added the target: patch This PR is targeted for the next patch release label Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: zones Issues related to zone.js target: patch This PR is targeted for the next patch release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants