sand-boxer/docs/bwrap-credentials.md
tegwick 17d4160b6e
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
feat: deliver owner-bound credentials into bwrap commands
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0726e-5232-73f2-aaca-2c05ceb62efb
2026-09-06 00:25:07 +02:00

68 lines
3.3 KiB
Markdown

# Bwrap owner credential delivery
Nonempty exec credential references now require an explicit owner-configured
route. Unknown or multiple references refuse. Empty references run without
credential acquisition. The owner binds exact allowed profile IDs, projects,
actors and a nonempty run ID before starting its configured exec provider.
These bindings are additional to manager/API consumer authentication.
The provider prefix is an absolute executable plus arguments ending in `--`.
It must implement exec-env delivery: consume its own approval and authentication,
inject ANTHROPIC_API_KEY only into the supplied child, and return the child's
exit status. The supplied child is sand-boxer's fixed host helper, not the
caller command. Its request travels on stdin; key values never travel on argv.
Only the helper sends the key over the private owner Unix channel into the
namespace broker. No key or OpenBao token is returned through the public API.
Owner extension configuration has this shape (proposal only):
```yaml
credential_routes:
glas-claude-agent-dev-anthropic:
profiles: [profile.claude-agent-dev-proof]
projects: [glas-harness]
actors: [agt]
exec_argv:
- /absolute/owner/venv/bin/python
- -m
- secrets_engine.cli
- exec
- --catalog
- glas-claude-agent-dev-anthropic
- --field
- ANTHROPIC_API_KEY
- --mode
- exec-env
- --auth
- service-jwt
- --
```
Do not install this example until the exact provider runtime, service identity,
approval contract and profile exist and are reviewed. No production route is
configured by this change. Owner config is trusted executable configuration;
API callers cannot change it. The parent shell's ANTHROPIC_API_KEY and
ANTHROPIC_AUTH_TOKEN are removed before provider invocation, so missing owner
acquisition cannot silently become interactive-shell delivery.
The broker injects only ANTHROPIC_API_KEY, validates nonempty bounded values,
and redacts exact byte sequences from stdout/stderr before truncation. A second
exec without a credential route has no key. Provider output is bounded and
captured; its errors are replaced by fixed messages. Envelope duration is the
command timeout plus 30 seconds of provider/cleanup budget. Provider failure or
invalid JSON refuses; SIGTERM and then SIGKILL bound stuck provider processes.
Engine/backend token revocation remains the provider's responsibility.
This is a delivery boundary for a trusted workload. It cannot prevent arbitrary
workload code from encoding the key, writing it into an artifact, or using it
against an allowed provider. Exact-output redaction is a backstop, not protection
against hostile code; artifact checks, profile admission and enforced egress
remain necessary. No key is written by the delivery mechanism itself.
Proof: scripts/smoke-bwrap-credentials.py uses a synthetic provider and a real
bwrap namespace. Sandbox 0e5fb35a proved child-only delivery, output redaction,
no leak into the next exec, wrong-project denial and teardown. No live OpenBao
or provider credential is involved. This does not activate CCR-2026-0016.
Native adoption is tracked in secrets-engine/SECRETS-WP-0009; production exec
currently refuses before OpenBao while exact-action authorization and engine
service authority are unavailable.