-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Protect against prototype pollution in core extend utility and markup parser #8578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| import { Debug } from '../../../core/debug.js'; | ||
|
|
||
| // markup scanner | ||
|
|
||
| // list of scanner tokens | ||
|
|
@@ -334,12 +336,19 @@ class Parser { | |
| // of assign) | ||
| function merge(target, source) { | ||
| for (const key in source) { | ||
| if (!source.hasOwnProperty(key)) { | ||
| if (!Object.prototype.hasOwnProperty.call(source, key)) { | ||
| continue; | ||
| } | ||
|
Comment on lines
337
to
341
|
||
|
|
||
| const isForbidden = key === '__proto__' || key === 'constructor' || key === 'prototype'; | ||
| Debug.assert(!isForbidden, `Ignoring forbidden property: ${key}`); | ||
| if (isForbidden) { | ||
| continue; | ||
|
Comment on lines
+343
to
+346
|
||
| } | ||
|
|
||
| const value = source[key]; | ||
| if (value instanceof Object) { | ||
| if (!target.hasOwnProperty(key)) { | ||
| if (!Object.prototype.hasOwnProperty.call(target, key)) { | ||
| target[key] = { }; | ||
| } | ||
| merge(target[key], source[key]); | ||
|
|
@@ -380,7 +389,7 @@ function resolveMarkupTags(tags, numSymbols) { | |
| const edges = { }; | ||
| for (let index = 0; index < tags.length; ++index) { | ||
| const tag = tags[index]; | ||
| if (!edges.hasOwnProperty(tag.start)) { | ||
| if (!Object.prototype.hasOwnProperty.call(edges, tag.start)) { | ||
| edges[tag.start] = { open: [tag], close: null }; | ||
| } else { | ||
| if (edges[tag.start].open === null) { | ||
|
|
@@ -390,7 +399,7 @@ function resolveMarkupTags(tags, numSymbols) { | |
| } | ||
| } | ||
|
|
||
| if (!edges.hasOwnProperty(tag.end)) { | ||
| if (!Object.prototype.hasOwnProperty.call(edges, tag.end)) { | ||
| edges[tag.end] = { open: null, close: [tag] }; | ||
| } else { | ||
| if (edges[tag.end].close === null) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extenditerates withfor...inbut does not filter inherited enumerable properties. This can copy unexpected keys fromex’s prototype chain and undermines the security hardening (a polluted prototype could inject additional enumerable keys). Consider adding anObject.prototype.hasOwnProperty.call(ex, prop)(orObject.hasOwn) guard inside the loop before copying.