Skip to content

Security Model

dcluomax edited this page Jun 1, 2026 · 1 revision

Security Model

This page summarizes Coop's threat model and the hardening shipped in main. The authoritative copy is SECURITY.md.

🚨 Reporting a vulnerability: do not open a public issue. Use GitHub's Private Security Advisory flow. We aim to respond within 5 business days and follow 90-day coordinated disclosure.

Threat model (v0.1 ALONE FARMER)

In scope: vault sealing/unsealing, hen workdir isolation, PTY shell auth bypass on loopback, brain key leakage in logs, tool sandbox escape.

Accepted out of scope for v0.1: non-bash tools run in-process in coopd (no kernel sandbox); the API + PTY WSS bind to 127.0.0.1 only unless you set COOP_API_TOKEN + COOP_PUBLIC=1.

Hardening shipped

ID Control
C1 file_read/file_write confine to the hen's workdir (no .., no /, symlink escapes rejected via canonicalization).
C2 http tool blocks SSRF: http/https only; loopback / RFC1918 / CGNAT / link-local / IPv6 ULA refused; redirects capped at 3 and re-validated per hop.
C3 WebSocket endpoints gated by Host/Origin allowlist (loopback only by default).
C4 Same middleware fronts the JSON API β†’ no cross-origin CSRF.
C5 Per-instance bash sandbox β€” macOS Seatbelt + Linux Bubblewrap confine each hen to its own workdir; siblings unreadable. Capability probe falls back to env-scrub + cwd; COOP_SANDBOX=0 disables.
C6 Per-hen network egress policy (off/allowlist/open) β€” see Network Isolation. Fail-closed if unenforceable.
H1 ~/.coop is 0700; vault.json and state.redb are 0600.
H2 Vault salt held in-memory; survives accidental file deletion mid-run.
H3 bash tool ignores model-supplied workdir; always the hen's workdir.
H6 WebSocket frames capped (/watch 64 KiB; /shell 256 KiB).
H7 bash env scrub β€” env_clear() + minimal allowlist; host secrets and one hen's env never leak into another's shell.
H8 Unique-per-instance workdir keyed on HenId::workdir_key() (<coop>__<name>).
M1 BYOK key heap-zeroized in Zeroizing<String>; Debug redacts it β€” never reaches logs/errors.
M2 Azure Key Vault BYOK β€” fetched over HTTPS with env-supplied AAD creds; secret held in Zeroizing, never written to disk; tokens/secrets redacted in Debug; error bodies truncated. See BYOK Secrets.
M3 Prompt length bound β€” over COOP_MAX_PROMPT_BYTES (default 256 KiB) β†’ HTTP 413.
M6 Discord connector default-denies (allowlist of user IDs).
L1 Farm UI's xterm.js loads with SRI (integrity=sha384-…).
LR1 Login throttle β€” COOP_LOGIN_MAX_ATTEMPTS (default 10) failures / 60s / IP β†’ HTTP 429.
LP1 Lease policy β€” CLI-framework pinning, allowed_tools subset wall, universal topic_filter on leased prompts.

Known limitations (accepted for v0.1)

  • Farm UI loads xterm.js from a CDN (with SRI); offline bundling planned.
  • GitHub Actions pinned by mutable tag; release artifacts unsigned (Sigstore on the v0.2 roadmap).
  • C6 v1 scope: under allowlist, bash/tmux get no direct egress β€” allow-listed egress flows only through the in-process http tool. The Linux forced-egress proxy for bash, SNI re-verification, and sentinel-token secret injection are documented follow-ups. tmux CLI agents aren't yet wrapped in the per-hen sandbox, so strict-policy hens with agent_kind != anthropic fail closed.

Related

Clone this wiki locally