Skip to content

Commit 9b62137

Browse files
MythologIQclaude
andcommitted
fix(vscode): residual sweep — stale docs, misleading comments, test gap
- Correct handleProtocols comment: ws library does NOT reject connections when false is returned; real auth is in the connection handler - Update serverHelpers.ts comment: token now via subprotocol, not query - Update HELP.md: reflect subprotocol auth and TTL eviction - Add null byte rejection test for isValidPythonPath - Add CSP security comments to all 4 legacy webview panels Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 08cdec0 commit 9b62137

File tree

8 files changed

+14
-7
lines changed

8 files changed

+14
-7
lines changed

packages/agent-os-vscode/HELP.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ violations today. Sortable and filterable.
124124
|---|---|---|
125125
| `'unsafe-inline'` for `style-src` in CSP | Required for VS Code theme CSS variable injection (`var(--vscode-*)`). Scripts remain nonce-gated. | Low -- style-only; no script injection vector. |
126126
| `retainContextWhenHidden: true` on Topology Detail | Preserves force-simulation state across tab switches (~120 animation frames). | Low -- adds ~2 MB memory when backgrounded. |
127-
| Session token in WebSocket URL query string | WebSocket upgrade requests cannot carry custom headers (RFC 6455). Token is 128-bit `crypto.randomBytes`. | Low -- server binds to 127.0.0.1; token never leaves loopback. |
128-
| Rate limiter Map without TTL eviction | Server is loopback-only, so the map holds at most one entry (127.0.0.1). | Negligible -- no memory growth risk. |
127+
| Session token via `Sec-WebSocket-Protocol` subprotocol | Token sent as subprotocol (not URL query string) to avoid proxy/debug logging. 128-bit `crypto.randomBytes`. | Low -- server binds to 127.0.0.1; token never leaves loopback. |
128+
| Rate limiter Map with TTL eviction | Stale entries evicted on each request. Server is loopback-only, so the map holds at most one entry (127.0.0.1). | Negligible -- no memory growth risk. |
129129
| `Math.random()` for burn-rate sparkline jitter | Synthetic demo data only, not used for any security or cryptographic purpose. | None -- replaced by real SRE data when backend connects. |
130130
| `axios` not used; `http` module for server | The governance server uses Node built-in `http`. No external HTTP client dependency. | N/A |
131131

packages/agent-os-vscode/src/server/GovernanceServer.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,15 @@ export class GovernanceServer {
197197
this._wsServer = new WebSocketModule.WebSocketServer({
198198
server: this._httpServer,
199199
path: '/',
200-
// Validate session token via subprotocol negotiation.
201-
// Client sends ['governance-v1', token]; we validate and accept 'governance-v1'.
200+
// Select 'governance-v1' subprotocol when token is present.
201+
// NOTE: handleProtocols does NOT reject connections — ws completes
202+
// the upgrade even when false is returned. Real auth is enforced
203+
// in the connection handler via validateWebSocketToken().
202204
handleProtocols: (protocols: Set<string>) => {
203205
if (protocols.has(this._sessionToken)) {
204206
return 'governance-v1';
205207
}
206-
return false; // reject connection
208+
return false;
207209
},
208210
}) as WebSocketServerLike;
209211

packages/agent-os-vscode/src/server/serverHelpers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ export function generateClientId(): string {
7070
*
7171
* @returns 32-character hex token
7272
*/
73-
// SECURITY: 128 bits of crypto.randomBytes for session auth. Transmitted in WS URL
74-
// query param (WebSocket upgrade has no custom header support per RFC 6455).
73+
// SECURITY: 128 bits of crypto.randomBytes for session auth. Transmitted via
74+
// Sec-WebSocket-Protocol subprotocol header (not URL query string, to avoid logging).
7575
export function generateSessionToken(): string {
7676
return randomBytes(16).toString('hex');
7777
}

packages/agent-os-vscode/src/test/services/sreServer.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ suite('isValidPythonPath', () => {
1717
test('rejects backticks', () => { assert.strictEqual(isValidPythonPath('`whoami`'), false); });
1818
test('rejects pipe', () => { assert.strictEqual(isValidPythonPath('python | cat'), false); });
1919
test('rejects dollar sign', () => { assert.strictEqual(isValidPythonPath('$HOME/python'), false); });
20+
test('rejects null bytes', () => { assert.strictEqual(isValidPythonPath('python\0'), false); });
2021
test('accepts python3', () => { assert.strictEqual(isValidPythonPath('python3'), true); });
2122
test('accepts unix path', () => { assert.strictEqual(isValidPythonPath('/usr/bin/python'), true); });
2223
test('accepts windows path', () => { assert.strictEqual(isValidPythonPath('C:\\Python311\\python.exe'), true); });

packages/agent-os-vscode/src/webviews/metricsDashboard/MetricsDashboardPanel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ export class MetricsDashboardPanel {
242242
<html lang="en">
243243
<head>
244244
<meta charset="UTF-8">
245+
<!-- SECURITY: 'unsafe-inline' for styles required by VS Code theme CSS variable injection. Scripts nonce-gated. -->
245246
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}'; img-src ${cspSource} https:; font-src ${cspSource};">
246247
<meta name="viewport" content="width=device-width, initial-scale=1.0">
247248
<title>Metrics Dashboard</title>

packages/agent-os-vscode/src/webviews/onboarding/OnboardingPanel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ export class OnboardingPanel {
230230
<html lang="en">
231231
<head>
232232
<meta charset="UTF-8">
233+
<!-- SECURITY: 'unsafe-inline' for styles required by VS Code theme CSS variable injection. Scripts nonce-gated. -->
233234
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}'; img-src ${cspSource} https:; font-src ${cspSource};">
234235
<meta name="viewport" content="width=device-width, initial-scale=1.0">
235236
<title>Welcome to Agent OS</title>

packages/agent-os-vscode/src/webviews/policyEditor/PolicyEditorPanel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ policies:
624624
<html lang="en">
625625
<head>
626626
<meta charset="UTF-8">
627+
<!-- SECURITY: 'unsafe-inline' for styles required by VS Code theme CSS variable injection. Scripts nonce-gated. -->
627628
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}'; img-src ${cspSource} https:; font-src ${cspSource};">
628629
<meta name="viewport" content="width=device-width, initial-scale=1.0">
629630
<title>Policy Editor</title>

packages/agent-os-vscode/src/webviews/workflowDesigner/WorkflowDesignerPanel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,7 @@ ${functionDefs}
626626
<html lang="en">
627627
<head>
628628
<meta charset="UTF-8">
629+
<!-- SECURITY: 'unsafe-inline' for styles required by VS Code theme CSS variable injection. Scripts nonce-gated. -->
629630
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}'; img-src ${cspSource} https:; font-src ${cspSource};">
630631
<meta name="viewport" content="width=device-width, initial-scale=1.0">
631632
<title>Workflow Designer</title>

0 commit comments

Comments
 (0)