GHSA-89vx-jh4q-vg3w
deepstream: PATCH_MULTI action bypasses Valve permission system allowing unauthorized record writes
Quick fix
GHSA-89vx-jh4q-vg3w — @deepstream/server: upgrade to the fixed version with the command below.
npm install @deepstream/server@10.1.1Details
## Summary
The `RECORD_ACTION.PATCH_MULTI` action is not registered in the Valve permission system's `RULES_MAP` (`src/services/permission/valve/rules-map.ts`). When `ConfigPermission.canPerformAction()` is called for a PATCH_MULTI message, `getRulesForMessage()` returns `null` because the action is missing from the map. This triggers an unconditional allow (`callback(..., null, true)`), completely bypassing all configured Valve permission rules.
Any authenticated user — regardless of their configured permissions — can write arbitrary data to any record using the PATCH_MULTI action.
## Root Cause
In `src/services/permission/valve/rules-map.ts` lines 38-54, the `RULES_MAP[TOPIC.RECORD].actions` dictionary maps record actions to permission rule types. The actions registered include: SUBSCRIBE, SUBSCRIBEANDHEAD, SUBSCRIBEANDREAD, READ, HEAD, LISTEN, CREATE, UPDATE, PATCH, NOTIFY, DELETE, ERASE. However, `RECORD_ACTION.PATCH_MULTI` is **absent** from this map.
When `getRulesForMessage()` at line 86-99 encounters an action not in the map, it returns `null`. In `config-permission.ts` at line 88-93, when `ruleSpecification === null`, the callback is invoked with `true` (allow) unconditionally.
## Attack Chain
1. Attacker authenticates with any valid credentials (even a minimal-privilege user) 2. Attacker sends a WebSocket message: `{topic: RECORD, action: PATCH_MULTI, name: "admin/secret-record", parsedData: [{path: "role", data: "admin"}]}` 3. `message-processor.ts:68` invokes permission check 4. `config-permission.ts:89` → `getRulesForMessage()` returns `null` for PATCH_MULTI 5. `config-permission.ts:92` → unconditional ALLOW 6. Record transition applies the operations — arbitrary record is modified
## Impact
- **Complete Valve permission bypass for record writes** — all configured permission rules are irrelevant - Any authenticated user can overwrite any record, including admin-only records - Mass record overwrites can destroy application state, corrupt sessions, cause service outage - Only exploitable when `permission.type` is set to `config` (Valve) — the recommended production configuration per deepstream documentation - Default permission type `none` (OpenPermission) allows everything already, so default deployments are unaffected
<details><summary>Proof of Concept</summary>
```javascript // Connect as a minimal-privilege user const { DeepstreamClient } = require('@deepstream/client'); const client = new DeepstreamClient('localhost:6020'); await client.login({ username: 'restricted-user', password: 'password' });
// This should be blocked by Valve permissions but isn't: // Send raw PATCH_MULTI message to bypass all permission rules const connection = client.getConnection(); connection.sendMessage({ topic: 0x52, // TOPIC.RECORD action: 0x50, // RECORD_ACTION.PATCH_MULTI (check actual enum value) name: 'admin/protected-record', parsedData: [ { path: 'permissions', data: 'admin' }, { path: 'secret', data: 'overwritten' } ] }); ``` </details>
## Suggested Fix
Add `PATCH_MULTI` to the RULES_MAP in `src/services/permission/valve/rules-map.ts`:
```typescript [RECORD_ACTION.PATCH_MULTI]: RULE_TYPES.WRITE, ```
This maps PATCH_MULTI operations to the same WRITE permission rule that governs UPDATE and PATCH.
## Affected Versions
All versions that include PATCH_MULTI support with the Valve (ConfigPermission) permission system. The PATCH_MULTI action was added in commit `82ffa8119d8f4a8242ac5c3507469a22de746b65` but was never registered in RULES_MAP.
## Credit
Vulnerability discovered by Zhixi "Jace" Sun of ASM/VI at TikTok.
Are you affected?
Enter the version of the package you're using.
Affected packages
References
- https://github.com/deepstreamIO/deepstream.io/security/advisories/GHSA-89vx-jh4q-vg3w[WEB]
- https://nvd.nist.gov/vuln/detail/CVE-2026-63116[ADVISORY]
- https://github.com/deepstreamIO/deepstream.io/commit/1c2adde6581c53ef47e204364bc740bc3c2e2e2a[WEB]
- https://github.com/deepstreamIO/deepstream.io[PACKAGE]
- https://github.com/deepstreamIO/deepstream.io/releases/tag/v10.1.1[WEB]