RFC-0002: Guest network egress and credential containment#100
Open
cspinetta wants to merge 5 commits into
Open
RFC-0002: Guest network egress and credential containment#100cspinetta wants to merge 5 commits into
cspinetta wants to merge 5 commits into
Conversation
418d169 to
be727e9
Compare
754b658 to
f049dd3
Compare
RFC-0002 (Draft) specifies one host-side mechanism governing what the untrusted guest agent can reach on the network and how it authenticates to the endpoints it may reach. Both concerns share a single low-privilege host proxy and its per-connection pipeline (`EgressPolicy`, `Tunnel`, `AuditSink`, and the credential injector), so the RFC specifies them together. Credential containment keeps durable secrets — API keys and OAuth refresh tokens — off the guest, injecting them at egress through a TLS-terminating proxy backed by a host credential store; the guest holds only non-secret placeholders. Downstream services declare injection through a `CredentialSpec` binding an upstream host to a header and a host-side secret source. Egress policy governs reachability, audit, and routing through a per-run profile (`open` default, `monitored`, `allowlist`, `proxy-only`, `none`), split between coarse network-layer pinning and fine-grained name-based policy at the proxy. Connection-to-run attribution is structural: a per-run rule denies a run every gateway hop but its own proxy listener, DNS, and enabled host-service ports, so one run cannot reach another's listener over the shared loopback. The per-run token authenticates on top — defense-in-depth on KVM, the primary cross-run control on VZ, where enforcement is in-guest. The RFC also covers cold-boot provisioning, snapshot-restore re-minting of the token and CA, per-box override semantics, the host-service exemption, and a `voidbox egress report` harvesting command. Index the RFC as 0002 in the RFC README; load-bearing decisions become ADRs once it is accepted.
Add design-doc prose conventions in docs/agents/doc-style.md, referenced from AGENTS.md, so design docs read as practical descriptions of what is built rather than prose that taxes the reader. Introduce a named component before referring to it — define what it is, who creates it, where it lives, its lifetime, and the problem it solves on first mention, then use the definite article. State the mechanism before claiming the property it produces, so a guarantee is earned rather than asserted, and avoid hype adjectives that assert quality without showing it. Don't narrate the document — cut sentences whose subject is the doc's own structure. Prefer the field's standard vocabulary over coined shorthand, metaphor, or unexpanded abbreviations. Each rule names the habit that causes the defect so reviewers can catch it at the point of use.
f049dd3 to
20e146e
Compare
… diagrams Replace the under-specified claim that the VZ reach floor is the existing blackhole-route deny-list "extended to express pin-to-proxy". That primitive matches on destination prefix only and cannot express the port-aware, default-deny allow-list pin-to-proxy requires (a run's own listener and a neighbor's differ by port on a shared gateway). VZ enforcement is instead a root-attached eBPF cgroup `connect4`/`connect6` (plus `sendmsg4`/`sendmsg6`) program that allow-lists egress by `(address, port)`, denies the rest with `EPERM`, and uses a `connect4` destination rewrite as the in-guest equivalent of the KVM DNAT. The required `CONFIG_CGROUP_BPF` and cgroup v2 are already present on both the production VZ kernel and the slim dev/test kernel, so no kernel rebuild is needed. Scope the guarantee to the threat model: against the modeled uid-1000 adversary — which holds no `CAP_BPF`/`CAP_NET_ADMIN`/`CAP_NET_RAW` — the filter is a boundary, not merely defense-in-depth; only a uid-1000→root escalation (kernel LPE or a guest-agent exploit), outside the primary model, can subvert it. The trust model now states explicitly that the only root in the guest is the trusted guest-agent (PID 1) while the workload runs as uid 1000. Add two mermaid diagrams to Connection attribution — per-run listeners (the arrival socket is the run's identity) and the KVM-vs-VZ enforcement point — and an Attribution-reliability paragraph that ties audit attribution to the per-run binding and bounds the beyond-model residual. Record the alternatives (a host userspace stack à la gvproxy as the bypass-resistant long-term answer, deferred to its own RFC; in-guest nftables) and why eBPF was chosen, plus the new risk (E8), the VZ uid-1000 bypass test, and the affected guest-agent and build-pipeline code.
Spell out Server-Side Request Forgery (SSRF) at its first occurrence and add a short gloss of the confused-deputy risk in R3, per the doc-style rule to expand abbreviations on first use. The terms stay (standard security terms of art); only the first-use expansion is added.
Clarify that selective routing (only credentialed clients pointed at the proxy) is the default-profile behavior; restrictive egress profiles route all traffic through the same proxy. Cross-reference §C so a reader of the credential-containment section does not over-generalize from the credential path to all egress.
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.
Summary
This is the discussion PR for RFC-0002: Guest network egress and credential containment (
docs/rfc/0002-guest-network-egress-and-credential-containment.md, statusDraft).RFC-0002 specifies a single host-side mechanism governing what the untrusted guest agent can reach on the network and how it authenticates to the endpoints it is allowed to reach. Both concerns rest on one shared, low-privilege host proxy and its per-connection handler pipeline (
EgressPolicy,Tunnel,AuditSink, and the credential injector), so the RFC specifies them together.What the RFC proposes
open/monitored/allowlist/proxy-only/none), orthogonal to credential containment and holding under any credential configuration. Defines the destination-reachability model, audit, and the split between coarse network-layer enforcement and fine-grained name-based policy at the proxy, with risk register E1–E7.Problem
The
claude-personalandcodexproviders stage OAuth credentials — including the refresh token — into the guest, and the API-key providers forward the raw key into the guest exec environment. A uid-1000 agent (via prompt injection or a compromised dependency) can read and exfiltrate these for access that outlives the run. Separately, there is today no way to restrict, audit, or rate-limit which destinations the guest may reach.Process
Per the RFC + ADR process (RFC-0001), this PR is the proposal and the venue for discussion and alternatives. Once accepted, the load-bearing decisions are distilled into ADRs, and implementation PRs link back to the RFC and ADR numbers.