P2 complete: Docker sandbox with kernel assertions + secret broker

tc-sandbox:
- SandboxSpec/SandboxDriver + DockerDriver (bollard): uid 10001, cap-drop
  ALL, no-new-privileges, embedded seccomp deny profile (unshare/ptrace/
  bpf/keyctl/mount/...), read-only rootfs with tmpfs /tmp + /home/agent,
  network=none, mem/cpu/pids limits
- agent-base image: non-root, all setuid binaries stripped
- 6 kernel-level assertion tests probing from INSIDE real containers:
  uid + CapEff==0, rootfs read-only, seccomp EPERM on unshare, zero
  traffic-carrying interfaces + failed egress connect, no setuid +
  NoNewPrivs=1, lifecycle

tc-secrets:
- ChaCha20-Poly1305 envelope encryption under a FileKey (generated 0600,
  AEAD tamper detection tested); secrets table ciphertext-at-rest
- teamclaw-broker daemon: length-prefixed JSON over a unix socket; no
  protocol operation ever returns plaintext; InvokeHttp independently
  consumes the single-use execution grant against Postgres BEFORE touching
  any credential, then performs the call itself with the secret injected
- Tests over the real socket + real Postgres + a real local HTTP receiver:
  encrypted at rest, pending approval refused, approved call carries the
  bearer token exactly once, grant replay refused, non-http URLs rejected

116 Rust + 61 frontend tests + 14 E2E journeys green.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-10 05:07:46 -05:00
co-authored by Claude Fable 5
parent de38449b41
commit ea5162ac65
19 changed files with 1473 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
//! The secret broker (spec §15): credentials live encrypted at rest and are
//! only ever used INSIDE the broker process — capability calls go in,
//! results come out, plaintext never crosses the socket. Gated capability
//! invocations independently consume the single-use execution grant against
//! Postgres before any credential is touched (defense in depth: a
//! compromised runtime cannot replay an approved action).
mod client;
mod crypto;
mod protocol;
mod server;
mod store;
pub use client::BrokerClient;
pub use crypto::{FileKey, Sealed};
pub use server::BrokerServer;
pub use store::SecretStore;
#[derive(Debug, thiserror::Error)]
pub enum BrokerError {
#[error("execution grant refused")]
GrantRefused,
#[error("invalid request: {0}")]
Invalid(String),
#[error("not found")]
NotFound,
#[error("crypto failure: {0}")]
Crypto(String),
#[error("io failure: {0}")]
Io(String),
}