Follow-up to the milestone-#12 evaluation (docs/security/CREDENTIAL_BROKER_EVALUATION.md), informed by nolabs-ai/nono — a shipped reference implementation of broker-not-mount (see docs/security/nono-comparison.md).
The borrow
nono keeps the real credential out of the sandbox entirely via a localhost reverse proxy + phantom token:
- Agent gets a per-session 256-bit phantom token (
NONO_PROXY_TOKEN), never the real key.
- Agent calls
http://127.0.0.1:<port>/<service>/...; the proxy validates the phantom token, swaps in the real credential, forwards over TLS. SDKs steered via OPENAI_BASE_URL/ANTHROPIC_BASE_URL — no agent code change.
cmd:// lazy host-side capture: durable creds (e.g. gh auth token, an OAuth refresh) run on the host on first use, cached with a TTL; the sandbox only ever sees the phantom token.
- L7
endpoint_rules scope a credential to specific method+path (closes exfil-to-allowed-host, THREAT_MODEL R3).
This is concretely sandy's eval A1 (durable cred stays host-side) and A2 (proxy-side injection). It also confirms the eval's central trade-off: to inject at the proxy you must terminate TLS — nono's proxy is TLS-terminating, whereas sandy's egress proxy is deliberately passthrough (proxy/config.go "never terminate"). So this is not a free extension of the existing sidecar; it's the deliberate no-MITM-invariant fork the eval's A2 describes.
Scope for this issue (Phase-1 slice)
- Spike a host-side credential broker exposing a localhost endpoint the container reaches (through the existing egress-proxy topology or a dedicated localhost forward), handing the container a phantom/short-lived token, not the raw key.
cmd://-style capture for the durable credential (start with gh auth token and the Claude/Gemini OAuth refresh-token → short-lived access-token case the eval's A1 already identified as the highest-value, no-provider-cooperation win).
- Decide the injection point: A1 (broker hands a short-lived token in, agent still makes the request) vs A2 (proxy injects, agent never holds it → requires the TLS-terminating fork). A1 first.
- Record the resolved posture (which creds brokered vs. still mounted) in
sandy-session.json, mirroring the effort field.
Explicitly out of scope (track separately)
- nono's isolation primitive (Landlock/seccomp-notify) — sandy's container is the stronger boundary; borrow the credential layer only.
- Full SPIFFE/per-tool child sandboxes — longer-horizon.
References
docs/security/nono-comparison.md, docs/security/CREDENTIAL_BROKER_EVALUATION.md (A1/A2), research/credential-broker-cb4a.md.
Follow-up to the milestone-#12 evaluation (
docs/security/CREDENTIAL_BROKER_EVALUATION.md), informed bynolabs-ai/nono— a shipped reference implementation of broker-not-mount (seedocs/security/nono-comparison.md).The borrow
nono keeps the real credential out of the sandbox entirely via a localhost reverse proxy + phantom token:
NONO_PROXY_TOKEN), never the real key.http://127.0.0.1:<port>/<service>/...; the proxy validates the phantom token, swaps in the real credential, forwards over TLS. SDKs steered viaOPENAI_BASE_URL/ANTHROPIC_BASE_URL— no agent code change.cmd://lazy host-side capture: durable creds (e.g.gh auth token, an OAuth refresh) run on the host on first use, cached with a TTL; the sandbox only ever sees the phantom token.endpoint_rulesscope a credential to specific method+path (closes exfil-to-allowed-host, THREAT_MODEL R3).This is concretely sandy's eval A1 (durable cred stays host-side) and A2 (proxy-side injection). It also confirms the eval's central trade-off: to inject at the proxy you must terminate TLS — nono's proxy is TLS-terminating, whereas sandy's egress proxy is deliberately passthrough (
proxy/config.go"never terminate"). So this is not a free extension of the existing sidecar; it's the deliberate no-MITM-invariant fork the eval's A2 describes.Scope for this issue (Phase-1 slice)
cmd://-style capture for the durable credential (start withgh auth tokenand the Claude/Gemini OAuth refresh-token → short-lived access-token case the eval's A1 already identified as the highest-value, no-provider-cooperation win).sandy-session.json, mirroring theeffortfield.Explicitly out of scope (track separately)
References
docs/security/nono-comparison.md,docs/security/CREDENTIAL_BROKER_EVALUATION.md(A1/A2),research/credential-broker-cb4a.md.