# Security Audit Report ## 1. Executive Summary This fix-mode audit reviewed the Nexus desktop app, VS Code extensions, local bridge process, frontend regression harness, prior audit findings, dependency manifests, and build/test configuration. The codebase is in a materially better posture than the earlier June audits: major Wails, SFTP, VNC proxy, GitHub API, import-size, SSH key generation, and frontend DOM issues were already fixed and covered by tests. Two remaining issues were confirmed and fixed in commit `3a16a14`: - The VS Code bridge's localhost HTTP server had no explicit header/body read timeouts and decoded JSON request bodies without a hard cap. - VS Code webview CSP nonces were derived from `Date.now()`, which made a script allow-list nonce predictable rather than cryptographically random. Verification passed with targeted bridge tests, full Go tests, frontend regression checks, frontend build, `npm audit --omit=dev`, `govulncheck`, JavaScript syntax checks, and `git diff --check`. ## 2. Scope Reviewed Reviewed: - Go backend packages under `internal/` and the `cmd/vscode-bridge` localhost JSON-RPC/SSE bridge. - Browser-facing frontend JavaScript and regression checks under `frontend/`. - VS Code extension webviews in `vscode/nexus/extension.js` and `vscode/leviathan/extension.js`. - Dependency manifests: `go.mod`, `go.sum`, `frontend/package.json`, `frontend/package-lock.json`, VS Code extension package manifests. - Build, release, and CI files including shell scripts and `.github/workflows/release-builds.yml`. - Existing audit reports under `audits/` to avoid duplicate findings. Not fully live-tested: - Packaged VS Code extensions inside a real VS Code host after the CSP nonce change. - Long-lived bridge event streams under deliberate slow-client conditions. - Packaged Wails binaries on all target operating systems. ## 3. Methodology I used static review, adversarial attack-surface mapping, dependency review, configuration review, DoS review, frontend/webview review, and targeted regression tests. I traced attacker-controlled inputs from webviews, the VS Code extension host, local HTTP requests, imported files, remote services, and session events into filesystem, process, network, DOM, and parser boundaries. Commands run: - `node --check vscode/nexus/extension.js` - `node --check vscode/leviathan/extension.js` - `node --check frontend/scripts/test-regressions.js` - `go test ./cmd/vscode-bridge -count=1` - `npm --prefix frontend test` - `git diff --check` - `go test ./... -count=1` - `npm --prefix frontend run build` - `npm --prefix frontend audit --omit=dev` - `go run golang.org/x/vuln/cmd/govulncheck@latest ./...` ## 4. Risk Rating Method Severity reflects attacker position, exploit practicality, affected trust boundary, and confidentiality/integrity/availability impact. Confidence reflects direct source evidence and regression coverage. - Critical: unauthenticated remote compromise or credential disclosure. - High: practical credential theft, code execution, or privilege escalation. - Medium: meaningful local, renderer, or connected-service abuse with realistic prerequisites. - Low: defence-in-depth or bounded local robustness issue. - Informational: hardening or validation gaps without a direct exploit path. ## 5. Attack Surface Map Entry points: - Wails-bound API methods callable from the renderer. - VS Code extension webviews and their `postMessage` handlers. - `cmd/vscode-bridge` localhost HTTP endpoints: `/health`, `/rpc`, `/events`, and `/runtime/event`. - SSH, SFTP, Telnet, RAW TCP, VNC, GitHub, IRC, local shell, updater, recording, export/import, and Leviathan binary-analysis workflows. Trust boundaries: - Renderer/webview to Go backend. - Local browser or extension host to localhost bridge. - Local selected files and profile imports to parsers. - Remote GitHub, SSH/SFTP/VNC/IRC/Telnet/RAW endpoints to client code. - OS keychain/vault to profile/session runtime. Attacker starting positions considered: - Local unprivileged process attempting bridge resource exhaustion. - Malicious or compromised extension webview state. - Hostile remote service data rendered into webviews. - Malicious selected local file or imported profile/export. - Compromised connected host attempting terminal/session abuse. ## 6. Findings Summary Table | ID | Severity | Confidence | Title | Component | Status | |---|---|---|---|---|---| | SEC-20260624-0945-001 | Low | High | VS Code bridge accepted unbounded HTTP parser work | `cmd/vscode-bridge` | Fixed in `3a16a14` | | SEC-20260624-0945-002 | Low | High | VS Code webview CSP nonces used predictable timestamps | `vscode/nexus`, `vscode/leviathan` | Fixed in `3a16a14` | ## 7. Detailed Findings ### Finding ID: SEC-20260624-0945-001 #### Title VS Code bridge accepted unbounded HTTP parser work #### Severity Low #### Confidence High #### Affected Files / Components - `cmd/vscode-bridge/main.go:120` - `cmd/vscode-bridge/main.go:212` - `cmd/vscode-bridge/main.go:230` - `cmd/vscode-bridge/main.go:336` - `cmd/vscode-bridge/main.go:346` - `cmd/vscode-bridge/main_test.go:11` - `cmd/vscode-bridge/main_test.go:28` - `cmd/vscode-bridge/main_test.go:48` #### Description The bridge listens only on localhost and requires a random bearer token, but the HTTP server previously used default server timeouts and decoded JSON bodies directly from `r.Body`. A local process, or a compromised component with bridge token access, could keep connections open or send oversized JSON to force unnecessary parser work and memory use. #### Evidence Before the fix, `server := &http.Server{Handler: mux}` used default timeout values, and `/rpc` plus `/runtime/event` called `json.NewDecoder(r.Body).Decode(...)` without `http.MaxBytesReader`. The fix adds explicit bridge limits at `cmd/vscode-bridge/main.go:50`, uses `newBridgeHTTPServer` at `cmd/vscode-bridge/main.go:126`, and applies `decodeLimitedJSON` in both POST handlers at `cmd/vscode-bridge/main.go:218` and `cmd/vscode-bridge/main.go:236`. #### Attack Scenario A local unprivileged process repeatedly connects to the bridge and sends slow headers or a large authenticated JSON body. Without timeouts and body caps, the bridge can spend disproportionate time and memory on unauthorised or oversized traffic. #### Impact Local denial of service against the VS Code extension bridge, causing sluggishness, failed RPCs, or event-stream disruption. #### Recommendation Set bounded HTTP server timeouts and header limits. Cap JSON request bodies before decoding. Keep long-lived SSE compatibility by avoiding a global `WriteTimeout` that would break event streams. #### Safer Example Implemented: ```go r.Body = http.MaxBytesReader(w, r.Body, bridgeMaxJSONBodyBytes) return json.NewDecoder(r.Body).Decode(dst) ``` #### Suggested Tests Added tests that assert bridge timeout/header settings and oversized `/rpc` plus `/runtime/event` bodies are rejected before reflective service dispatch. #### References - CWE-400: Uncontrolled Resource Consumption - OWASP ASVS 12.1: File and resource handling - OWASP API Security Top 10 API4: Unrestricted Resource Consumption #### Assumptions / Limitations The practical attacker is local, because the bridge binds to `127.0.0.1`. The bearer token remains an important control, but it is not a substitute for parser and server resource limits. ### Finding ID: SEC-20260624-0945-002 #### Title VS Code webview CSP nonces used predictable timestamps #### Severity Low #### Confidence High #### Affected Files / Components - `vscode/nexus/extension.js:5` - `vscode/nexus/extension.js:10` - `vscode/nexus/extension.js:219` - `vscode/nexus/extension.js:554` - `vscode/nexus/extension.js:895` - `vscode/nexus/extension.js:1061` - `vscode/nexus/extension.js:1162` - `vscode/nexus/extension.js:1260` - `vscode/nexus/extension.js:1375` - `vscode/nexus/extension.js:1618` - `vscode/nexus/extension.js:1832` - `vscode/leviathan/extension.js:5` - `vscode/leviathan/extension.js:10` - `vscode/leviathan/extension.js:189` - `vscode/leviathan/extension.js:497` - `vscode/leviathan/extension.js:773` - `frontend/scripts/test-regressions.js:222` #### Description The VS Code webviews use CSP script nonces, but each nonce was previously `String(Date.now())`. CSP nonces are intended to be high-entropy, per-render allow-list values. A timestamp nonce is guessable and weakens CSP if an HTML injection primitive is introduced elsewhere. #### Evidence All `const nonce = String(Date.now());` occurrences in the VS Code extension files were replaced with `createCSPNonce()`, backed by `crypto.randomBytes(16).toString('base64')`. #### Attack Scenario An attacker finds or later introduces a webview HTML injection path that can emit a `