Repository navigation
Description
The question
Can a host-side classifier tell a likely data-extraction attempt from an ordinary read, well enough to choose between auto-allow, ask and block for a tainted session's outgoing calls? Which signals carry the decision, and does JEV improve on deterministic heuristics enough to justify its cost, latency and data flow?
The classifier runs only once a session is tainted (G6, "Untrusted input (G6)", docs/decisions/governed-writable-workers.md:3760). It judges each outgoing call at admission:
- WebFetch URL and prompt;
- the full Bash command (
curl -d …,gh … --body …); - MCP and
brainCLI arguments; - provider-relay request bodies.
It does not see wire traffic. For HTTPS the turn proxy sees only CONNECT host:port and byte counts (packages/ui-sdk/src/server/egress-proxy.ts). Tool-call admission already sees full inputs: the Claude PreToolUse chain (packages/ui-backend-claude/src/permission-hooks.ts:546-578), the outward plan (prepareOutwardPlan, packages/ui-sdk/src/server/outward-policy.ts:45), and the provider relay.
What is blocked on the answer
#3430 was ruled on 2026-11-03: a tainted interactive session asks (a permission card per new host, with a session-scoped grant) rather than refusing. This spike measures whether a classifier can keep that prompt rare. If every new host asks, prompts become frequent enough to be rubber-stamped. A reliable classifier would let clean reads through and reserve the card for suspicious calls. The spike starts once #3430 is delivered, so it measures against the real prompt path.
How it gets answered
-
Signals, deterministic first. Implement and score each one separately:
- fingerprint overlap: shingle hashes of the outgoing request against brain files read in the session, the strongest signal;
- the destination host appears in the content that tainted the session;
- high-entropy or encoded blobs (base64, hex) in the path, query or subdomain;
- query length and body size to a host the session has not used before;
- write-shaped destinations: mail, issues, gists, paste sites, form endpoints;
- fan-out: many calls or many distinct subdomains to one new host;
- the request method and the tool's own read/outward classification.
-
JEV as the middle-band judge. Run it only where the heuristic score is ambiguous. Its input is limited to the outgoing request, the name of the taint source and the overlap score. It never sees the conversation or the untrusted content, so the same injection cannot steer it.
-
Labelled set. Use keyless Odysseus fixtures:
- benign reads after a taint: lookups, documentation fetches, public APIs,
ghreads, image prompts; - extraction attempts: brain text in a query string, base64 in a subdomain, a POST of a note to a paste site, chunked trickles, paraphrased leaks, an injected "send this to …" instruction.
Include adversarial cases written to evade each heuristic.
- benign reads after a taint: lookups, documentation fetches, public APIs,
-
Measure precision and recall per action band (allow, ask, block) for heuristics alone and for heuristics plus JEV. Also measure latency and per-call cost, and the ask rate on a realistic benign session.
Constraints the design must hold:
- Advisory only. It can escalate a call from allow to ask or block. It never relaxes
deny,allowlistmode, budgets or outward-action rules. - Its own data flow. The JEV call sends request content to a provider. Route it under "Data-to-provider routing (G2)" (
docs/decisions/governed-writable-workers.md:2395), meter it and budget it. When JEV is unavailable, the band falls back to ask. - Append-only history. No verdict enters the provider-facing conversation, except as the text of a refusal in that call's own tool result.
- Keyless tests. Tests use a deterministic JEV stub, and live measurement stays out of CI.
- Voice and autonomous turns stay on refusal, whatever the verdict.
Time box
Three working days for signals, the labelled set and measurement. Stop early if fingerprint overlap alone reaches high recall at an acceptable ask rate: that is a valid outcome, and JEV stays out.
Deliverable
A comment on this issue, or a docs/plans/ entry if it is large, containing:
- the signal definitions and the request schema the classifier sees;
- the labelled set, checked in as a keyless fixture;
- the measured table per configuration;
- a recommendation: heuristics only, heuristics plus JEV, or no classifier.
Then file implementation tasks under #3428 from it. Name the known evasions the classifier cannot catch, so the approval card stays the backstop.
Out of scope
- Implementing the classifier in the admission path; implementation tasks are filed under Epic: session taint marks real untrusted input, and its restrictions are visible and decidable #3428 from the deliverable.
- Changing
deny,allowlistmode, budgets, outward-action rules or what taints a session (ui-server: an ordinary shell command taints a governed session even when the egress proxy records real connections #3429). - Wire-level inspection of HTTPS traffic.
Acceptance criteria
- The signal definitions and the request schema the classifier sees are written down.
- The labelled set (benign and extraction cases, including adversarial evasions per heuristic) is checked in as a keyless Odysseus fixture.
- A table reports precision and recall per action band, latency, per-call cost and the benign-session ask rate, for heuristics alone and, unless the early-stop condition is met, for heuristics plus JEV.
- The recommendation names the configuration and the known evasions the classifier cannot catch.
- Live JEV measurement (unless the early-stop condition is met) stays within the $10 cap, runs outside CI, and the deliverable records spend, model version and sanitized results.
- Implementation tasks are filed under Epic: session taint marks real untrusted input, and its restrictions are visible and decidable #3428.
Verification
Keyless tests over the fixture with a deterministic JEV stub run in CI. Any live JEV measurement is run outside CI under the recorded authorization above (cap $10), with spend, model version and sanitized results in the deliverable; no credential or account identifier in public evidence.
Contract impact
None for the spike. Implementation tasks state their own.
Live JEV authorization (maintainer, 2026-11-03)
The JEV leg is authorized: the model this spike specifies, a per-issue spend cap of $10, the maintainer's credential, run outside CI. The deliverable records the spend, the model version and sanitized results; no credential or account identifier appears in public evidence. If the cap is reached before the measurement is complete, stop and report what was measured.
Blocked by #3430
Triage 2026-11-03: verified the blocker (#3430 is open with needs: decision) and stated the ordering from epic #3428's breakdown; re-verified the G6 (:3760), G2 (:2395) and prepareOutwardPlan (:45) citations at 3d3516a02; added out of scope, acceptance criteria, verification and contract impact.
Triage 2026-11-03: folded the maintainer ruling (JEV leg authorized: spec'd model, $10 cap, maintainer credential, outside CI); removed needs: human; #3430 now ruled (ask) but not delivered, so still blocked.
Activity
schlessera commentedon Nov 3, 2026
Triage 2026-11-03: added
needs: human. Measuring JEV needs live provider calls, and no recorded authorization covers this spike: the standing #838 authorization names only #923–#925. Needed: a maintainer comment here that either authorizes the JEV leg (model, spend cap, credential access) or rules the spike heuristics-only. Still blocked by #3430, which hasneeds: decision.schlessera commentedon Nov 3, 2026
Decision (maintainer, 2026-11-03): the JEV leg is authorized: the model the spike specifies, a per-issue spend cap of $10, the maintainer's credential, outside CI. Spend, model version and sanitized results are recorded in the deliverable. Removed
needs: human; the body's prerequisite section now records the authorization, and there is an acceptance criterion for the cap. #3430 has been ruled (ask) but is not delivered, soblockedandBlocked by #3430stay. Brief complete:agent-ready(blocked).