Commit Graph
3 Commits
Author SHA1 Message Date
Omar SobhandClaude Fable 5 a26939d7bc Plan hardening: socket-proxy allowlist, gateway load test, offline verify
- The compose server NEVER sees the raw Docker socket (plan risk #5):
  tecnativa/docker-socket-proxy on an isolated engine_net with exactly
  CONTAINERS/POST/EXEC/DELETE/VERSION allowed; server reaches it via
  DOCKER_HOST. DockerDriver honors DOCKER_HOST (connect_to). Proven by a
  REAL proxy test: full sandbox lifecycle works through the allowlist
  while /networks, /secrets, and /images all 403 — the blast-radius cap
  if the server is ever owned. (This also fixes compose deployments,
  where sandbox provisioning previously had no engine access at all.)
- Gateway load test (plan P6): 40 concurrent SSE streams against one
  server — every run completes with the full §13 event vocabulary,
  every journal strictly monotonic, every resumeFrom=0 replay byte-equal
  to its live stream
- release.yml: SBOMs (syft, spdx-json) for all four images shipped
  INSIDE the signed bundle; final verification now runs in a
  --network none container — proving the customer's verify path needs
  no internet, not just claiming it

159 Rust tests.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-10 10:50:55 -05:00
Omar SobhandClaude Fable 5 84c51168be P6: strict seccomp allowlist + K8s sandbox driver proven on kind
- images/seccomp/agent-profile.json is now a TRUE ALLOWLIST: Docker's
  default profile (vendored from moby v27.5.1, defaultAction ERRNO) with
  18 syscalls an agent never needs stripped from the allow groups
  (unshare, ptrace, bpf, mount family, setns, module loading,
  perf_event_open, process_vm_*, reboot, quotactl, ...); arch map trimmed
  to x86_64 + aarch64. All 6 Docker kernel assertions still green.
- K8sDriver (tc-sandbox feature 'k8s', kube-rs): one hardened pod per
  sandbox — runAsUser 10001, cap-drop ALL, no-new-privs via
  allowPrivilegeEscalation=false, RuntimeDefault seccomp, read-only
  rootfs with emptyDir /tmp + /home/agent, resource limits, no service
  account token — in a PSS-restricted namespace carrying a default-deny
  NetworkPolicy (applied server-side apply, idempotent). Exec via the API
  server attach channel with exit codes parsed from v1.Status.
- Live suite (feature 'k8s-tests') against a REAL kind cluster: uid /
  CapEff==0 / NoNewPrivs / rootfs probes from inside pods, PSS label +
  deny-all policy asserted via the API, lifecycle. Honest limits in the
  rustdoc: Localhost seccomp profile and CNI-enforced egress are
  per-cluster provisioning (kindnet does not enforce NetworkPolicy).
- rustls 0.23 process provider pinned to ring at driver connect.
- CI: dedicated sandbox-k8s job (helm/kind-action) running the suite.

149 Rust tests + 3 live kind tests; clippy clean including the k8s feature.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-10 09:00:56 -05:00
Omar SobhandClaude Fable 5 ea5162ac65 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]>
2026-06-10 05:07:46 -05:00