github akitaonrails/ai-jail v2.0.0

4 hours ago

v2.0.0

ai-jail 2.0 is the "control and visibility" release: filtered egress, a
launch audit log, and credential-file hygiene. Fully backward-compatible —
every v1.x config keeps working unchanged; everything below is opt-in.

Added

  • Filtered egress: --allow-host / allow_hosts. Between "no network"
    and "all network" there is now a third mode: the sandbox can reach exactly
    the hosts you allow, over TCP, via CONNECT — and nothing else.
    ai-jail --allow-host api.anthropic.com --allow-host github.com claude.
    Entries match the host and its subdomains; private, loopback, link-local,
    CGNAT, multicast, and cloud-metadata addresses are refused after DNS
    resolution (which happens once — the checked answer is the one dialed, so
    DNS rebinding gets nothing).

    Enforcement is kernel-level, not a polite suggestion: on Linux the sandbox
    keeps its private network namespace with no external route at all, and a
    tiny in-sandbox bridge (spawned before Landlock/seccomp apply, so it alone
    stays unrestricted) forwards loopback TCP to the proxy over a bind-mounted
    Unix socket; on macOS the seatbelt profile allows outbound only to
    localhost:<proxy-port>. The proxy itself is ~400 auditable std-only
    lines — no TLS termination, no CA, no new dependencies. Proxy-unaware
    processes that ignore http_proxy simply fail, which is the safe
    direction. Honest caveats (in README and docs/SECURITY.md): an allowed
    host is trusted wholesale, and on macOS the system resolver is not fenced.
    Design and rationale: docs/connect-proxy-plan.md and
    docs/openshell-comparison.md.

  • Launch audit log: --audit-log / audit_log = true. Appends one
    JSONL record per launch (command, effective capabilities, config sources,
    exit code, duration) to ~/.local/share/ai-jail/history.jsonl (0700 dir,
    0600 file, symlinks refused). With filtered egress active, the proxy also
    records every CONNECT allow/deny verdict — "what did the agent try to
    reach?" is now answerable. Off by default; a project .ai-jail can
    disable but never enable it.

  • --env-from-file PATH. Reads KEY=VALUE lines from a strictly
    validated file (user-owned, mode 0600, not a symlink, outside the
    project) and injects them like --env, with --env winning conflicts.
    Never persisted to any config file; project .ai-jail cannot set it.
    This codifies the credential pattern: secrets live in the host
    environment or a 0600 file, never in an .ai-jail file.

  • Launch warnings learned filtered mode. Known API clients no longer
    warn about network when filtered egress covers their API host — and do
    warn, naming the host, when it doesn't.

Fixed

  • Filtered egress + --lockdown no longer deadlocks the allowlist on
    kernels ≥ 6.7: lockdown's Landlock V4 ruleset now allows ConnectTcp to
    the in-sandbox bridge port (safe — inside the private netns that port is
    loopback-only), everything else stays denied.
  • The proxy's SSRF guard also refuses multicast and deprecated
    v4-compatible IPv6 addresses.

Changed

  • --allow-tcp-port remains disabled (UDP cannot be isolated); its error
    now points at --allow-host, which supersedes it. The Landlock V4 port
    machinery stays for lockdown.

Checksums (SHA256)

f3af60744ba2a57f6b46568a16cdbe1c625c30f9bf99f1e5099f695849963113  ai-jail-linux-x86_64.tar.gz
98f3edddb312d74cc32a8c51367a28fbc27e8bec9574ed2a45d6825fd92aaabf  ai-jail-macos-aarch64.tar.gz

Install

brew tap akitaonrails/tap && brew install ai-jail
yay -S ai-jail-bin
cargo install --locked ai-jail

Don't miss a new ai-jail release

NewReleases is sending notifications on new releases.