Coordinated Disclosure Timeline
- 09/30/2020: maintainer notified
- 01/04/2021: disclosure deadline, no maintainer response
- 01/04/2021: created issue on project as final attempt to notify maintainer
- 01/05/2021: maintainer acknowledges report and is working on a patch
- 01/13/2021: version 3.03 released to npm
Summary
Merge-deep actively attempts to prevent prototype pollution by blocking object property merges into __proto__
, however it still allows for prototype pollution of Object.prototype
via a constructor
payload.
Product
merge-deep 3.0.2 (latest version)
Tested Version
3.0.2
Details
merge-deep
can be tricked into overwriting properties of Object.prototype
or adding new properties to it. These properties are then inherited by every object in the program.
Here is an example, in which we assume that payload
is provided by an attacker, and isAdmin
is a property that is later on used to check whether a user is authorized to perform some sensitive operation:
var mergeDeep = require("merge-deep");
var payload = '{"constructor": {"prototype": {"isAdmin": true}}}';
mergeDeep({}, JSON.parse(payload));
After this code has run, Object.prototype.isAdmin
is true
. But Object.prototype
is on the prototype chain of most objects, so we also have {}.isAdmin == true
, and indeed u.isAdmin == true
for most other objects u
, including, perhaps, objects used to represent users.
It is important to note that the above code snippet throws an exception (since Object.prototype
cannot be reassigned), but it still sets the property (since it can be mutated). In some settings this might make the vulnerability difficult to exploit, but in others (for example web servers, which generally are written to be tolerant to route-handler crashes) it will still be easily exploitable.
Impact
JavaScript prototype pollution can lead to a variety of application context specific impacts ranging from Denial of Service (DoS) to Remote Code Execution (RCE).
Credit
This issue was discovered and reported by GitHub team member @max-schaefer.
Contact
You can contact the GHSL team at securitylab@github.com
, please include GHSL-2020-160
in any communication regarding this issue.