From 608b8ce5555b6739636628b6bf94c4e65e740cb5 Mon Sep 17 00:00:00 2001 From: "will.anderson" Date: Sat, 22 Aug 2026 12:54:33 -0500 Subject: [PATCH] docs(audit): part 9 - root cause analysis, behavior-direction layer --- FORK-AUDIT.md | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/FORK-AUDIT.md b/FORK-AUDIT.md index 3d4d889193..120acdb42e 100644 --- a/FORK-AUDIT.md +++ b/FORK-AUDIT.md @@ -320,3 +320,93 @@ confirmed, this item stays open. **Containment:** local config only; never committed, never pushed. But it did reach a session log, which is precisely the leak channel this section warns about — logged here so the gate failure is on record. + +--- + +# PART 9: FULL ROOT-CAUSE ANALYSIS - THE BEHAVIOR-DIRECTION LAYER +## (2026-08-22, deep examination session) + +Method note: this pass used READING, not grepping. Keyword sweeps missed +everything below because nothing signs its work. Findings are behavioral. + +## RC#1: REMOTE BEHAVIOR INJECTION (proven end-to-end) +config/config.ts (~L360-395): for every auth entry of type "wellknown", +the app fetches {provider}/.well-known/opencode, reads remote_config +{url, headers}, fetches that URL, and MERGES the returned JSON into the +GLOBAL config layer. +The remote config schema (core/src/v1/config/config.ts) includes: + - instructions[] (behavioral instruction files) + - agent{} (agent definitions incl. system prompts) + - permission{} (what the agent may do) + - mcp{} (which external servers get wired) + - default_agent, server{ hostname, mdns, cors } +Any authenticated provider can silently reshape agent behavior on the +user's machine. Logged only at Effect.logDebug level - invisible at +normal verbosity. Live code path in every binary built tonight. +Endpoint state 2026-08-22: opencode.ai serves 404 to anonymous curl - +BUT responses are server-discretionary per client (fingerprinting is +referenced in their own webfetch tool); dormancy cannot be assumed. + +## RC#2: NETWORK EXPOSURE VIA SAME VECTOR +Remote/global config carries server{hostname, mdns}. mdns:true flips +binding to 0.0.0.0 and broadcasts via Bonjour as "opencode-{port}" +(server/mdns.ts, default domain opencode.local). A remote config can +expose the entire agent API to the LAN without any CLI flag. +Default without mdns: 127.0.0.1 (loopback). + +## RC#3: THIRD-PARTY DATA OUTFLOW +tool/mcp-websearch.ts: websearch defaults through mcp.exa.ai and +search.parallel.ai. Sends queries + session_id + model_name outbound. +EXA_API_KEY passed IN URL QUERY STRING (leaks to intermediary logs). +Responses parsed loosely (SSE lines) into agent context with minimal +validation = second injection surface. + +## RC#4: TELEMETRY ON LLM TRAFFIC +agent/agent.ts + session/llm.ts attach OpenTelemetry tracers to model +calls. Export destination via OTEL_EXPORTER_OTLP_ENDPOINT/HEADERS env. +control-plane/workspace.ts (L533-535) PROPAGATES these variables to +remote workspaces. Trace metadata of AI conversations is remotely +redirectable by whoever controls the control plane. + +## RC#5: FLEET-MANAGEMENT ARCHITECTURE +- server/mdns.ts: LAN self-broadcast (Bonjour) +- control-plane/workspace.ts: persistent SSE connections to remote + targets at /global/event, header-authenticated, per-workspace + ConnectionStatus tracking; pluggable workspace adapters +- server/routes/instance/httpapi: wide route surface incl. + /experimental/console/orgs, /experimental/console/switch, + /experimental/workspace/warp, /experimental/worktree/reset, + /auth/:providerID, /command, /file, /api/event + Authorization middleware present but named Experimental*; + coverage not yet audited line-by-line. +- plugin/meta.ts: plugin fingerprinting + first_seen/last_seen/ + load_count usage tracking +- server/shared/fence.ts + fence middleware: x-opencode-sync event- + sequence headers syncing instances to controllers + +## SHAPE VERDICT +A local coding agent implemented as a managed fleet node: instructable +remotely, exposable remotely, observable remotely. Every mechanism +dressed as configuration; every trace hidden at debug log level. + +## REMEDIATION ORDER (for rebuild) +1. Config from local ledger only; remote proposals visible+approved, + never silent merges. DELETE well-known fetch path. +2. Loopback-only binding as constitutional default; no config may + widen it. mDNS deleted or opt-in-per-session with loud warning. +3. No third-party intermediaries without explicit per-session consent. + Keys never in URLs. MCP results validated or rejected. +4. Telemetry physically absent from source, not toggle-off. +5. All fleet plumbing (control-plane SSE, org routes, sync headers, + fingerprinting) deleted; replaced by user-owned EventBus visibility. + +## STILL UNEXAMINED (queued next sessions) +acp/ internals (3.5k lines), cli/ (20k lines), session/ end-to-end +data flow, cli/tui/worker.ts listener chain, server/routes/instance/ +httpapi handler-by-handler audit. + +## GUARD STATUS +Our egress guard (src/guard/index.ts, installed at CLI entrypoint) +already logs all outbound requests to ~/.local/state/neuron-guard.jsonl +and blocks vendor hosts in NEURON_GUARD=strict mode. It would have +caught RC#1/RC#3 traffic on day one.