Prototype Pollution in deepmerge-ts
Description
deepmerge-ts is vulnerable to Prototype Pollution via the defaultMergeRecords() function, allowing attackers to pollute object prototypes.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
deepmerge-ts is vulnerable to Prototype Pollution via the defaultMergeRecords() function, allowing attackers to pollute object prototypes.
Vulnerability
The deepmerge-ts TypeScript library (versions prior to 4.0.2) is vulnerable to Prototype Pollution in the defaultMergeRecords() function within deepmerge.ts [1][3]. When merging objects, the function does not properly filter or block the __proto__ property, allowing an attacker to inject properties into the global Object.prototype [3].
Exploitation
An attacker can exploit this by supplying a crafted object containing a __proto__ key with arbitrary properties as one of the inputs to the deepmerge() function [4]. No authentication or special privileges are required; the attacker only needs to control the content of an object passed to the merge operation. The provided test payload demonstrates the attack: '{"__proto__":{"a0":true}}' [4].
Impact
Successful exploitation results in Prototype Pollution, where properties are added to Object.prototype. This can lead to unexpected behavior across the application, including denial of service, property injection, and potentially arbitrary code execution if the polluted properties are used in security-sensitive contexts (e.g., property access checks) [1][3]. The scope of impact depends on how the merged objects are used downstream.
Mitigation
The vulnerability has been patched in version 4.0.2 [1][3]. Users should upgrade to this version or later immediately. There are no known workarounds for this issue [1]. The fix includes a test that verifies the prototype is not polluted after merging [4].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
deepmerge-tsnpm | < 4.0.2 | 4.0.2 |
Affected products
2- RebeccaStevens/deepmerge-tsv5Range: < 4.0.2
Patches
2b39f1a93d9e1Merge pull request #86 from RebeccaStevens/security/prototype-pollution
2 files changed · +26 −1
src/deepmerge.ts+10 −1 modified@@ -438,7 +438,16 @@ function defaultMergeRecords< continue; } - result[key] = propertyResult; + if (key === "__proto__") { + Object.defineProperty(result, key, { + value: propertyResult, + configurable: true, + enumerable: true, + writable: true, + }); + } else { + result[key] = propertyResult; + } } /* eslint-enable functional/no-loop-statement, functional/no-conditional-statement */
tests/deepmerge.test.ts+16 −0 modified@@ -539,3 +539,19 @@ test(`merging objects with null prototype`, (t) => { t.deepEqual(merged, expected); }); + +test("prototype pollution", (t) => { + const payload = '{"__proto__":{"a0":true}}'; + + const x: any = JSON.parse(payload); + const y: any = {}; + + const merged: any = deepmerge(x, y); + + t.deepEqual(JSON.stringify(merged), payload); + + t.not(({} as any).a0, true, "Safe POJO"); + t.not(x.a0, true, "Safe x input"); + t.not(y.a0, true, "Safe y input"); + t.not(merged.a0, true, "Safe output"); +});
d637db7e4fb2fix: protect against prototype pollution
2 files changed · +26 −1
src/deepmerge.ts+10 −1 modified@@ -438,7 +438,16 @@ function defaultMergeRecords< continue; } - result[key] = propertyResult; + if (key === "__proto__") { + Object.defineProperty(result, key, { + value: propertyResult, + configurable: true, + enumerable: true, + writable: true, + }); + } else { + result[key] = propertyResult; + } } /* eslint-enable functional/no-loop-statement, functional/no-conditional-statement */
tests/deepmerge.test.ts+16 −0 modified@@ -539,3 +539,19 @@ test(`merging objects with null prototype`, (t) => { t.deepEqual(merged, expected); }); + +test("prototype pollution", (t) => { + const payload = '{"__proto__":{"a0":true}}'; + + const x: any = JSON.parse(payload); + const y: any = {}; + + const merged: any = deepmerge(x, y); + + t.deepEqual(JSON.stringify(merged), payload); + + t.not(({} as any).a0, true, "Safe POJO"); + t.not(x.a0, true, "Safe x input"); + t.not(y.a0, true, "Safe y input"); + t.not(merged.a0, true, "Safe output"); +});
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-r9w3-g83q-m6hqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-24802ghsaADVISORY
- github.com/RebeccaStevens/deepmerge-ts/commit/b39f1a93d9e1c3541bd2fe159fd696a16dbe1c72ghsax_refsource_MISCWEB
- github.com/RebeccaStevens/deepmerge-ts/commit/d637db7e4fb2bfb113cb4bc1c85a125936d7081bghsax_refsource_MISCWEB
- github.com/RebeccaStevens/deepmerge-ts/security/advisories/GHSA-r9w3-g83q-m6hqghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.