capture: port the shell's packet-capture subsystem as a governed sidecar#85
Merged
Conversation
The native macOS shell had a full network-visibility subsystem (BBPacketCapture + BBNetworkMonitor + BBFirewall) that never made it into the Gecko build. This ports it as capture-sidecar/ — a loopback-only Rust sidecar (cloned from the iot-sidecar shape) providing the same three surfaces cross-platform: - Packet capture: engine detect (dumpcap > tshark > tcpdump, +Windows paths), whole-session capture on 'any', live line stream over /events WS, save pcap. - Connection map: eTLD+1 + tracker/analytics/cdn classifier ported verbatim from the shell; browser feeds observations via POST /map. - Firewall: per-domain Ask/Allow/Block, persisted to JSON. Governance (the reason this is a sidecar, not ObjC): every side effect is classified by the canonical agent-control-bridge --surface capture. Packet capture START and pcap EXPORT are the exfiltration vectors, so they are prohibited by default and reclassify to gated ONLY on an explicit cockpit user gesture (actor=user AND userGesture=true) — an injected/agent planner can never silently record or export traffic. Fail-closed on any gate error. Also fixes a pre-existing bridge bug: CLI --param values weren't coerced, so 'userGesture=true' arrived as a string and gesture-gated conditions could NEVER permit via the CLI path (the path the Rust gates use) — only via the in-process API the tests used. Now coerced via _parse_flow, so the enforced path matches the tested path. iot containment test still 20/20. Proven: - capture-sidecar unit tests (eTLD/classify/firewall) pass - test_capture_injection_containment.py 16/16: agent capture/export BLOCKED, forged gesture BLOCKED, user-gesture+token PERMITTED, reads allowed - live binary smoke: detects dumpcap, classifies doubleclick.net=tracker, agent capture-start -> HTTP 403, loopback-only bind - build-capture-sidecar.sh: cargo build + 3-way smoke (refuses ungoverned, /health 200, agent capture 403) Not yet wired: cockpit panel UI + auto-launch in assemble-cockpit/cockpit-up + runtime/cockpit-config base. Next commit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The native macOS shell had a full network-visibility subsystem — packet capture (
BBPacketCapture, tshark/tcpdump), a live connection map (BBNetworkMonitor), and a per-domain firewall (BBFirewall) — that never made it into the production Gecko build. This ports the whole thing ascapture-sidecar/, a loopback-only Rust sidecar (cloned from theiot-sidecarshape), so it works on Linux/Windows/macOS.Surfaces
any, live line stream over/eventsWS, save pcap (dumpcap writes real pcapng; text engines buffered).POST /map.Governance (why a sidecar, not ObjC)
Every side effect goes through the canonical
agent-control-bridge.py --surface capture. Packet-capture START and pcap EXPORT are the exfiltration vectors, so they'reprohibitedby default and reclassify togatedonly on an explicit cockpit user gesture (actor=userANDuserGesture=true). An injected/agent planner can never silently record or export traffic. Fail-closed on any gate error, mirroring the iot sidecar's one-engine invariant.Also fixes a pre-existing bridge bug
CLI
--paramvalues weren't coerced, souserGesture=truearrived as a string and gesture-gated conditions could never permit through the CLI — the exact path the Rust sidecar gates use (only the in-process API the tests used worked). Now coerced via_parse_flow, so the enforced path matches the tested path. The iot containment test stays 20/20.Verified
capture-sidecarunit tests (eTLD / classify / firewall round-trip) passtest_capture_injection_containment.py16/16 — agent capture/export BLOCKED, forged gesture BLOCKED, user-gesture+token PERMITTED, reads alloweddoubleclick.net=tracker,POST /capture/start(agent) → HTTP 403, loopback-only bindbuild-capture-sidecar.sh— cargo build + 3-way smoke (refuses ungoverned start,/health200, agent capture 403)Not in this PR (next commit)
The cockpit panel UI + auto-launch wiring (
assemble-cockpit.shstaging,bearbrowser-cockpit-uplaunch + port,runtime/cockpit-config.jsbase). This PR is the proven engine + governance; the visible-in-browser surface layers on next — same split the iot-sidecar already followed.