fix(enforce): fail closed on --enforce for GUI editors (Cursor) - #112
fix(enforce): fail closed on --enforce for GUI editors (Cursor)#112johnnyfish wants to merge 1 commit into
Conversation
Found and fixed a second Cursor blocker: a rotated gateway CATesting the GUI launch on a real machine surfaced Root cause: two different CAs share the subject name Only the key differed. Verified by checking the served leaf against each: The runbook made this reachable: it pointed Changes
VerificationAgainst the real machine, before the fix: After re-trusting: warning silent, Unit tests cover the trap directly (same-name/different-key must not compare equal, same cert must compare equal so the warning doesn't become noise, live CA findable among stale ones, empty PEM must not truncate). Linux |
Second CA bug on the same machine: installed but not trustedAfter fixing the rotated CA, Cursor still failed with The trap. The documented command was:
Dropping Changes
Linux Status of the Cursor demo
|
Make --enforce trustworthy end to end instead of silently degrading: - Fail closed on --enforce for GUI editors (Cursor) and launch them inside the OneCLI sandbox so their traffic is actually governed. - Make headless cursor-agent a first-class enforceable agent. - Verify the gateway CA is trusted (not merely installed) and detect a rotated CA before it breaks GUI editors. - Add transparent redirect: an SNI-recovering listener, fail-closed pf anchor management nested under com.apple, a setgid helper so pf can scope redirection by group, an opt-in transparent sandbox profile, and session lifecycle with fail-closed teardown. - Cover it with live TLS proof, pf anchor, and full-chain tests, plus the Cursor coverage demo runbook.
b79425d to
43979f6
Compare
What
onecli run --enforce -- cursornow fails closed with a clear message instead of silently sandboxing nothing.Why
Cursor (and other VS Code-style GUI editors) aren't launched-and-owned by
onecli run: the command only opens/focuses an already-running Electron app, so there's no child process tree to confine. Under--enforcethe wrap path would:sandbox-execthe launcher — which hands off to the running app and governs nothing, and127.0.0.1:<port>) into Cursor's persistentsettings.json, leaving the editor pointed at a dead proxy after the run ends.I hit #2 live: a prior enforce-cursor run had left
"http.proxy": "http://127.0.0.1:59845"in real settings.Change
Route agents whose spec has
configDirset (the GUI/VS Code-style marker that already drivesinjectElectronProxySettings) to a fail-closed error that points at the supported cooperative path:Mirrors the existing docker-sandbox (Hermes) fail-closed case. The cooperative path (
onecli run -- cursor) is unchanged and self-heals a stale port by re-injecting the real gateway URL.Test
TestGUIEditorsMarkedForEnforceRejection: pins that Cursor carriesconfigDir(so the fail-closed route fires) and that a CLI agent (Codex) does not.Verification
Reproduced both CI jobs in Linux Docker before pushing:
golang:1.26.0:go build ./...+go test -race ./...— all passgolangci/golangci-lint:v2.10:golangci-lint run ./...— 0 issuesFollows #105 (now merged).