From 614f87b8f2eb86e8d4887727b69ccd9d3cac4605 Mon Sep 17 00:00:00 2001 From: Andy Dixon Date: Wed, 24 Jun 2026 09:47:59 +0100 Subject: [PATCH] docs: add security audit reports --- .../20260624-0945-functionalityNextSteps.md | 79 ++++ audits/20260624-0945-securityAudit.md | 361 ++++++++++++++++++ 2 files changed, 440 insertions(+) create mode 100644 audits/20260624-0945-functionalityNextSteps.md create mode 100644 audits/20260624-0945-securityAudit.md diff --git a/audits/20260624-0945-functionalityNextSteps.md b/audits/20260624-0945-functionalityNextSteps.md new file mode 100644 index 0000000..3849904 --- /dev/null +++ b/audits/20260624-0945-functionalityNextSteps.md @@ -0,0 +1,79 @@ +# Functionality and Next Steps Report + +## 1. Executive Summary + +This fix-mode pass improved VS Code extension robustness by hardening the local bridge and webview CSP handling. The highest-impact next step is runtime validation in a real VS Code host: the source-level tests pass, but the extension panels and long-lived bridge event stream deserve manual smoke coverage after the HTTP timeout and nonce changes. + +The codebase already has useful regression coverage for prior security fixes. The main opportunity now is to reduce duplicated webview HTML patterns and add integration tests around the VS Code bridge, because that surface currently depends heavily on static checks. + +## 2. Current Functional Risks + +- VS Code bridge `/events` uses a long-lived SSE stream. The new server has read/header/idle limits but intentionally no global write timeout, so a real VS Code smoke test should confirm events still flow correctly during SSH/SFTP/VNC/GitHub sessions. +- VS Code webview HTML is duplicated across many panel classes. CSP, nonce generation, escaping, and message wiring are now correct in reviewed files, but duplication increases future regression risk. +- The Node extension bridge client reads bridge responses without an explicit response-size cap or request timeout. The bridge is local and trusted, but a stuck bridge can still degrade the extension UX. +- Frontend/webview coverage is mostly static regression assertions. It catches known bug patterns but does not prove that panels render and handlers fire inside VS Code. + +## 3. Code Quality Improvements + +- Centralise webview scaffolding in `vscode/nexus/extension.js` and `vscode/leviathan/extension.js`: CSP generation, nonce creation, common style policy, and HTML shell construction should live in one helper per extension or a shared local module. +- Wrap bridge HTTP requests in a small client helper with timeout, response-size cap, JSON decode error handling, and consistent error messages. +- Consider replacing large inline template-string webviews with smaller render helpers that build trusted static shell plus escaped dynamic content. The current approach is workable, but it makes security review repetitive. +- Keep the bridge handler helpers small and testable. `newBridgeHTTPServer` and `decodeLimitedJSON` are a useful pattern for future endpoints. + +## 4. Frontend Interaction and Error-Handling Improvements + +- Add manual smoke steps for Nexus Connections, terminal, RAW, GitHub, IRC, VNC, Profile Editor, Settings, SFTP, Leviathan Tools, Leviathan Hex, and Leviathan tool panels. +- Add non-sensitive `console.error` or visible status handling for JSON parse failures in VS Code webview message handlers where currently errors may be silent. +- Validate that reconnect, resize, SFTP directory actions, GitHub refresh/download, and Leviathan tool execution still fire their expected events after panel reloads. +- Confirm no webview logs secrets, bearer tokens, passwords, passphrases, private key material, or raw sensitive bridge responses. + +## 5. Testing Roadmap + +- Unit tests: keep `cmd/vscode-bridge` tests for server settings and body caps; add request method/auth tests for all bridge routes. +- Integration tests: add socket-level bridge tests for slow headers, oversized headers, and idle connection cleanup. +- VS Code extension smoke tests: exercise webview creation, command registration, bridge startup, one RPC, and one event frame. +- Frontend interaction tests: use a browser/DOM harness for key Wails UI flows where practical, especially SFTP upload, profile import, SSH key management, and Leviathan mode switching. +- Abuse-case tests: retain oversized import/upload/config tests and add edge cases whenever new parsers or bridge endpoints are introduced. +- Release smoke tests: package VSIX files and assert expected files, CSP strings, media resources, and bridge executable permissions. + +## 6. Recommended New Functionality + +- Add an in-extension bridge diagnostics command that shows bridge status, version, last RPC error, and whether the event stream is connected, without exposing the bearer token. +- Add a developer-only test command for the VS Code extension that opens each webview and posts a benign fixture state. This would make manual and automated smoke testing faster. +- Add a small security status page or command that reports vault state, known-host policy, update-check source, and active local bridge address without sensitive values. + +## 7. Next-Level Opportunities + +- Create a shared webview rendering module for both Nexus and Leviathan extension panels, with typed helpers for CSP, escaping, buttons, and event wiring. +- Introduce structured bridge RPC method allow-list metadata rather than reflective method dispatch alone. Reflection is convenient, but a visible allow-list would make the trust boundary easier to review. +- Add observability around bridge request counts, rejected oversized requests, active event clients, and session lifecycle errors. +- Add accessibility checks for VS Code webview panels, especially keyboard focus, button labels, and status updates in terminal/disconnected flows. + +## 8. Prioritised Action Plan + +Immediate: + +- Smoke-test the committed fix in a real VS Code host. +- Confirm `/events` remains stable during session state changes. + +Short-term: + +- Add bridge client timeout and response-size caps in the Node extension code. +- Add VS Code extension smoke tests for panel construction and bridge RPC. +- Consolidate CSP nonce creation and webview HTML policy helpers. + +Medium-term: + +- Replace static-only regression assertions with executable DOM or VS Code integration tests for high-value panels. +- Add bridge route coverage for auth failures, method errors, malformed JSON, and event subscription lifecycle. + +Long-term: + +- Build a release validation pipeline for desktop app, bridge binary, and VSIX packages. +- Add structured diagnostics and observability for local bridge health and rejected requests. + +## 9. Caveats and Validation Needed + +- Source and automated tests passed, but VS Code runtime behaviour was not manually exercised in this pass. +- The CSP nonce change should be behaviour-preserving, but every webview panel should still be opened once in VS Code. +- The bridge timeout settings are conservative for local RPC; long-running operations should continue reporting progress through events rather than blocking a single HTTP request indefinitely. diff --git a/audits/20260624-0945-securityAudit.md b/audits/20260624-0945-securityAudit.md new file mode 100644 index 0000000..7b50fbd --- /dev/null +++ b/audits/20260624-0945-securityAudit.md @@ -0,0 +1,361 @@ +# 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 `