defaults-deep CVE-2018-16486
Prototype Pollution in defaults-deep via constructor.prototype.
The problem
defaults-deep <= 0.2.4 (all published versions) is affected by
CVE-2018-16486 (CWE-1321 Prototype Pollution). The published package has
no fix available — exactly what npm audit reports. `defaults-deep` recursively copies source properties into a target. The published version guards against a literal `__proto__` key but still recurses through `constructor` into `constructor.prototype`, allowing an attacker-controlled source object (e.g. parsed from untrusted JSON) to add or overwrite properties on `Object.prototype` for the whole process.
The fix — drop-in, no code changes
Add an overrides entry so every direct and transitive dependency on
defaults-deep resolves to the patched fork, then reinstall:
{
"overrides": {
"defaults-deep": "npm:@keep-lts/defaults-deep@^0.2.5"
}
}
Equivalent for Yarn: use resolutions. The public API is unchanged — nothing else to do.
✓ Live on npm: @keep-lts/defaults-deep · or install directly: npm i @keep-lts/defaults-deep
What we changed
Keys that name a prototype slot (`__proto__`, `constructor`, `prototype`) are skipped during the recursive merge, so no source data can reach `Object.prototype`. Legitimate deep-default behavior is unchanged — real configuration data does not contain these reserved section names.
Proof of concept (the vulnerability)
const defaultsDeep = require('defaults-deep');
defaultsDeep({}, JSON.parse('{"constructor":{"prototype":{"polluted":"yes"}}}'));
console.log(({}).polluted); // => 'yes' (Object.prototype polluted)
@keep-lts/defaults-deep@0.2.5How we keep it trustworthy
- Minimal, surgical patch — security only, no feature changes.
- A regression test that fails on the original and passes on the patch; legitimate behaviour preserved.
- Published under the
@keep-ltsorg with the full advisory and tests inside the package; upstream license & attribution retained.
Full advisory and changelog ship inside the package (SECURITY.md, CHANGELOG.md).