VYPR
Critical severityNVD Advisory· Published Aug 9, 2022· Updated Sep 16, 2024

Prototype Pollution

CVE-2022-25907

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.

PackageAffected versionsPatched versions
ts-deepmergenpm
< 2.0.22.0.2

Affected products

2

Patches

1
9be514877334

prevent against prototype pollution

https://github.com/voodoocreation/ts-deepmergeRaice HannayJul 10, 2022via ghsa
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

News mentions

0

No linked articles in our index yet.