GHSA-2mhw-wcx5-v3xj: Medium severity npm/scim-patch vulnerability
Summary
Incomplete Prototype Pollution Fix Allows Mutation of Inherited Built-in Method Objects
scim-patch blocks direct dangerous path segments such as proto, constructor, and prototype, but still traverses inherited properties when applying SCIM patch paths.
An attacker who controls a SCIM PATCH operation can use paths such as toString.polluted to mutate shared built-in function objects, for example Object.prototype.toString.
Impact
A malicious patch can add attacker-controlled properties to inherited built-in method objects. The impact is narrower than direct Object.prototype pollution, but the mutation is process-global and may affect application logic that reads properties from inherited methods.
Details
Affected code paths:
- navigate() reads inherited properties via schema[subPath] - assign() uses key in obj, which treats inherited properties as existing
Because inherited keys are followed, safe-looking path segments such as toString can resolve to shared built-in objects.
PoC
js const assert = require("node:assert/strict"); const { scimPatch } = require("./lib/src/scimPatch");
const victim = { schemas: ["urn:ietf:params:scim:schemas:core:2.0:User"], userName: "alice", active: true, emails: [{ value: "alice@example.com", primary: true }], meta: { created: "x", lastModified: "x", resourceType: "User" } };
try { assert.equal(({}).toString.scimPatchPolluted, undefined);
scimPatch(victim, [ { op: "add", path: "toString.scimPatchPolluted", value: "polluted" } ]);
assert.equal(({}).toString.scimPatchPolluted, "polluted"); console.log(({}).toString.scimPatchPolluted); } finally { delete Object.prototype.toString.scimPatchPolluted; }
Output:
text polluted
A no-path operation with a dotted value key is also affected:
js scimPatch(victim, [ { op: "add", value: { "toString.noPathPolluted": "polluted" } } ]);
Remediation
Do not traverse inherited properties while resolving patch paths. Use own-property checks such as Object.hasOwn(obj, key) and create missing containers only for safe own keys.
Keep the existing denylist for proto, constructor, and prototype as defense in depth.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/scim-patchto a version that resolves this vulnerability.Fixed in 0.9.2 - Compensating control
When resolving SCIM PATCH paths, do not traverse inherited properties: use own-property checks such as Object.hasOwn(obj, key), create missing containers only for safe own keys, and retain the denylist for __proto__, constructor, and prototype as defense in depth.
Event History
Frequently Asked Questions
What level of access does an attacker need to exploit this issue?
The attacker must be able to control a SCIM PATCH operation. No user interaction is required.
What can be modified by a successful malicious patch?
A patch path using an inherited name such as toString can resolve to a shared built-in method object and add attacker-controlled properties to it. The resulting mutation is process-global, although it is narrower than direct Object.prototype pollution.
Why do blocked path segments not fully prevent exploitation?
Although direct __proto__, constructor, and prototype segments are blocked, the affected path handling follows inherited properties. navigate() reads inherited values through schema[subPath], and assign() treats inherited keys as existing through key in obj.