Skip to content

Commit bca70f8

Browse files
test(server): structural assertion that dispatch path holds no Map<RequestId,> state
1 parent b0d286d commit bca70f8

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { readFileSync } from 'node:fs';
2+
import { dirname, join } from 'node:path';
3+
import { fileURLToPath } from 'node:url';
4+
5+
import { describe, expect, test } from 'vitest';
6+
7+
/**
8+
* Structural guard for GHSA-345p (cross-tenant routing via id-keyed shared state).
9+
*
10+
* The original vulnerability shape was a `Map<RequestId, ...>` (or equivalent) on a
11+
* long-lived object that routes per-request data. The `dispatch(req, env)` path yields
12+
* its outputs into a per-call iterator with no id-keyed routing map; this test asserts
13+
* that property structurally so a future change cannot quietly reintroduce the shape.
14+
*
15+
* Intentionally NOT covered: `StreamDriver._responseHandlers` (outbound correlation for
16+
* requests this side initiates over a persistent channel) is a `Map<RequestId, ...>` but
17+
* is not in the inbound dispatch path and is not the GHSA shape. `shttpHandler` keys its
18+
* abort map on `(sessionId, requestId)`, not bare `RequestId`.
19+
*/
20+
describe('GHSA-345p structural guard: no id-keyed maps in inbound dispatch path', () => {
21+
const here = dirname(fileURLToPath(import.meta.url));
22+
const files = [
23+
join(here, '../../core/src/shared/dispatcher.ts'),
24+
join(here, '../src/server/mcp.ts'),
25+
join(here, '../src/server/shttpHandler.ts')
26+
];
27+
28+
/**
29+
* Matches the field-declaration shapes that produced GHSA-345p:
30+
* `: Map<RequestId, ...>`
31+
* `new Map<RequestId, ...>`
32+
* `: Map<string | number, ...>` (RequestId's underlying union)
33+
* `Record<RequestId, ...>`
34+
*/
35+
const idKeyedMapPattern = /(?::\s*|new\s+)Map<\s*(?:RequestId|string\s*\|\s*number)\b|Record<\s*RequestId\b/;
36+
37+
for (const file of files) {
38+
test(`${file.split('/packages/')[1]} has no Map<RequestId, ...> field declarations`, () => {
39+
const src = readFileSync(file, 'utf8');
40+
const matches: string[] = [];
41+
for (const [i, line] of src.split('\n').entries()) {
42+
if (idKeyedMapPattern.test(line)) {
43+
matches.push(` ${i + 1}: ${line.trim()}`);
44+
}
45+
}
46+
expect(matches, `id-keyed map declarations found:\n${matches.join('\n')}`).toEqual([]);
47+
});
48+
}
49+
});

0 commit comments

Comments
 (0)