Answer the GLAS-WP-0015 handoff for SAND-WP-0015-T04 without activating any production path. Add candidate profile profile.claude-agent-dev-proof v1.1.0 (ext.bwrap, localhost-only, default: deny, declared api.anthropic.com:443) for GLAS-WP-0012 review. The committed profile grants no egress by itself — ext.bwrap refuses it unless owner extension config independently allowlists the destination — and a regression test asserts that fail-closed default. Reconcile the differing project examples in favour of the acceptance runner's actor agt / project glas-local-proof, keeping the documented credential route bound to that single project rather than broadening it. Record the return contract (profile revision, host scope, consumer tuple, runtime digest and mount paths, declared egress, value-free denial/cleanup receipts) in docs/bwrap-runtime.md. T04 stays wait: Claude credential lane, owner machine authentication, pinned Claude executable and real-model acceptance remain operator gated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HjyScPKb8MV8y2VZHGFSSV Assistant: claude-code Assistant-Model: opus Assistant-Process: 716401@bnt-lap001 Assistant-Session: 0d02392b-d4a8-4fed-98e3-32333f768169
75 lines
3.7 KiB
Markdown
75 lines
3.7 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-local-proof]
|
|
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
|
|
- --
|
|
```
|
|
|
|
The consumer tuple is exactly `actor: agt`, `project: glas-local-proof`,
|
|
`profile.claude-agent-dev-proof` — the identity the Glas real acceptance runner
|
|
presents. The earlier `glas-harness` example in this document was a generic
|
|
consumer illustration, not a reviewed binding, and is superseded here. The route
|
|
stays bound to that single project; it is not broadened to every Glas project,
|
|
and `glas-harness` remains only a generic consumer name in unrelated fixtures.
|
|
|
|
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.
|