Guard deepMerge against prototype pollution#10108
Closed
gunjanjaswal wants to merge 2 commits into
Closed
Conversation
Contributor
There was a problem hiding this comment.
Welcome! It looks like this is your first pull request in Blockly, so here are a couple of tips:
- You can find tips about contributing to Blockly and how to validate your changes on our developer site.
- We use conventional commits to make versioning the package easier. Make sure your commit message is in the proper format or learn how to fix it.
- If any of the other checks on this PR fail, you can click on them to learn why. It might be that your change caused a test failure, or that you need to double-check the style guide.
Thank you for opening this PR! A member of the Blockly team will review it soon.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The basics
The details
Resolves
Fixes #10048
Proposed Changes
deepMergewalkssourcewithfor...inand never skips the prototype-pollution keys, so a source object with an own enumerable__proto__(which is exactly whatJSON.parseproduces) gets written ontoObject.prototypeduring the recursive merge. This adds a small guard that skips__proto__,constructor, andprototypebefore merging each key.Reason for Changes
Blockly.utils.object.deepMergeis a public, package-root-reachable API. If a host app passes any user-influenced data through it,deepMerge({}, JSON.parse('{"__proto__":{"x":"y"}}'))setsObject.prototype.x, which then leaks onto every plain object in the process (CWE-1321). The guard is minimal and leaves behavior unchanged for all normal keys.Test Coverage
Added a case to the existing
deepMergemocha suite inutils_test.js: it merges aJSON.parse('{"__proto__": {"blocklyPolluted": "yes"}}')payload into{}and assertsObject.prototype.blocklyPollutedstaysundefined. It fails before the guard and passes after. I don't have the Blockly build toolchain set up locally, so I leaned on the added test plus CI rather than a local full run.Documentation
None needed, behavior is unchanged for normal keys.
Additional Information
On #10048 a maintainer mentioned you might prefer to drop
deepMergein favor of the spread operator. Happy to do that instead if you'd rather remove the function than harden it; this guard is the minimal fix in the meantime.