Prototype Pollution
Description
ts-deepmerge before 2.0.2 is vulnerable to Prototype Pollution via the merge function due to missing sanitization, allowing attackers to pollute Object.prototype.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
ts-deepmerge before 2.0.2 is vulnerable to Prototype Pollution via the merge function due to missing sanitization, allowing attackers to pollute Object.prototype.
Vulnerability
Overview
The package ts-deepmerge prior to version 2.0.2 is susceptible to Prototype Pollution [1]. The vulnerability arises because the merge function does not sanitize input that can manipulate properties like __proto__, constructor, or prototype [2]. When merging objects, recursive assignment is performed without checking for these special properties, allowing an attacker to inject arbitrary properties into the global Object.prototype [3].
Exploitation
An attacker can exploit this by providing a crafted object as one of the arguments to the merge function [4]. This object can contain a __proto__ property (or other prototype chain properties) that, when merged, pollutes the base object prototype. No authentication is required other than the ability to supply the malicious input to the merge operation. The attack can be performed remotely if the application merges user-controllable data [3].
Impact
Successful exploitation leads to Prototype Pollution, which can result in denial of service (by triggering JavaScript exceptions), modification of application behavior, or in some scenarios, remote code execution [1][3]. Polluted properties are inherited by all objects, potentially bypassing security checks or altering expected application flow.
Mitigation
The vulnerability is fixed in version 2.0.2 [2]. Users should upgrade to this version or later. The fix involved adding proper sanitization to prevent prototype pollution. No workarounds are documented, so upgrading is the recommended action [1].
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 |
|---|---|---|
ts-deepmergenpm | < 2.0.2 | 2.0.2 |
Affected products
2- ts-deepmerge/ts-deepmergedescription
Patches
19be514877334prevent against prototype pollution
6 files changed · +1253 −1045
jest.config.js+2 −2 modified@@ -11,7 +11,7 @@ module.exports = { }, globals: { "ts-jest": { - tsConfig: { + tsconfig: { target: "es6", }, }, @@ -20,8 +20,8 @@ module.exports = { preset: "ts-jest", roots: ["<rootDir>/src"], testEnvironment: "jsdom", + testEnvironmentOptions: { url: "http://localhost" }, testMatch: ["**/*.test.{ts,tsx}"], - testURL: "http://localhost", transformIgnorePatterns: ["/node_modules/.+\\.js$"], verbose: true, };
.npmrc+1 −0 added@@ -0,0 +1 @@ +registry=https://registry.npmjs.org/
package.json+13 −12 modified@@ -3,7 +3,7 @@ "author": "Raice Hannay <voodoocreation@gmail.com>", "description": "A TypeScript deep merge function.", "license": "ISC", - "version": "2.0.1", + "version": "2.0.2", "keywords": [ "typescript", "deep", @@ -23,9 +23,9 @@ "test": "cross-env NODE_ENV=test jest --no-cache --config ./jest.config.js", "test:all": "npm-run-all format typecheck lint test:coverage", "test:coverage": "cross-env NODE_ENV=test jest --no-cache --coverage --config ./jest.config.js", - "typecheck": "tsc" + "typecheck": "tsc", + "prepack": "tsc" }, - "prepublish": "tsc", "repository": { "type": "git", "url": "git@github.com:voodoocreation/ts-deepmerge.git" @@ -36,18 +36,19 @@ "homepage": "https://github.com/voodoocreation/ts-deepmerge#readme", "types": "dist/index.d.ts", "devDependencies": { - "@types/jest": "^27.0.2", - "@typescript-eslint/eslint-plugin": "^5.0.0", + "@types/jest": "^28.1.4", + "@typescript-eslint/eslint-plugin": "^5.30.5", "cross-env": "^7.0.3", - "eslint": "^8.0.0", + "eslint": "^8.19.0", "eslint-config-voodoocreation": "^2.0.1", - "eslint-plugin-import": "^2.25.1", - "eslint-plugin-jest": "^25.0.5", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jest": "^26.5.3", "eslint-plugin-prefer-arrow": "^1.2.3", - "jest": "^27.2.5", + "jest": "^28.1.2", + "jest-environment-jsdom": "^28.1.2", "npm-run-all": "^4.1.5", - "prettier": "^2.4.1", - "ts-jest": "^27.0.5", - "typescript": "^4.4.4" + "prettier": "^2.7.1", + "ts-jest": "^28.0.5", + "typescript": "^4.7.4" } }
src/index.test.ts+12 −0 modified@@ -142,4 +142,16 @@ describe("merge", () => { expect(merge(object1, object2, object3).array).toEqual(["a", "b", "c"]); }); }); + + describe("reported vulnerabilities", () => { + it("safeguards against prototype pollution", () => { + const merged: any = merge( + {}, + JSON.parse('{ "__proto__": { "hasProto": true } }') + ); + + // eslint-disable-next-line no-proto + expect(merged.__proto__.hasProto).toBe(undefined); + }); + }); });
src/index.ts+6 −0 modified@@ -23,11 +23,17 @@ const isObject = (obj: any) => { return false; }; +const PROTECTED_KEYS = ["__proto__"]; + const merge = <T extends IObject[]>( ...objects: T ): TUnionToIntersection<T[number]> => objects.reduce((result, current) => { Object.keys(current).forEach((key) => { + if (PROTECTED_KEYS.includes(key)) { + return; + } + if (Array.isArray(result[key]) && Array.isArray(current[key])) { result[key] = merge.options.mergeArrays ? Array.from(new Set((result[key] as unknown[]).concat(current[key])))
yarn.lock+1219 −1031 modified
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-7qqq-gh2f-wq76ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-25907ghsaADVISORY
- github.com/voodoocreation/ts-deepmerge/commit/9be5148773343c57be9de39728d6ead18eddf10bghsax_refsource_MISCWEB
- github.com/voodoocreation/ts-deepmerge/releases/tag/2.0.2ghsax_refsource_MISCWEB
- security.snyk.io/vuln/SNYK-JS-TSDEEPMERGE-2959975ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.