github akitaonrails/ai-jail v1.20.0

4 hours ago

Fixed

  • --display delivers WAYLAND_DISPLAY again, so graphical apps start.
    bwrap applies argv in sequence, so --clearenv discards every --setenv
    before it. The display and systemd-user variables were emitted ahead of the
    environment-hardening block that carries --clearenv, so both were dropped
    while their sockets stayed bound: --display bound the Wayland socket
    without telling the client where it was, clients fell back to wayland-0,
    and ai-jail --browser=soft --network --display --gpu chromium died with
    Failed to connect to Wayland display. --systemd-user lost
    DBUS_SESSION_BUS_ADDRESS the same way, which left the socket fix from
    v1.19.1 unusable. Present since v1.18.0 (#122).

    XDG_RUNTIME_DIR hid this for five releases. It is pushed alongside
    WAYLAND_DISPLAY but also rescued independently by the XDG_ prefix in the
    default environment allowlist, so the one variable people check to confirm
    the display is wired up was the one that survived by accident.

    No capability widens. Both sets are still populated only under their existing
    opt-in (--display, --x11, --systemd-user), both remain empty under
    --lockdown, and the values are the ones discovery already validated. One
    precedence note: --env WAYLAND_DISPLAY=... combined with --display now
    loses to the discovered value, matching how the SSH and Claude variables have
    always behaved.

Added

  • jcode is a recognized agent. It was in none of the agent tables, so
    --agent-state did nothing for it and the private-home tmpfs hid everything
    it needed — mapping its config directory by hand did not help, because agent
    state is keyed off the invoked command name and jcode matched nothing.
    --agent-state jcode now exposes ~/.jcode (config, credentials, and the
    per-provider OAuth files) and ~/.config/jcode (provider env files on
    Linux). Reported by @jschaeff (#108).

    jcode also reads ~/.claude for Claude Code compatibility, and that is
    deliberately not included: mounting another agent's credential directory on
    the strength of a command name is a broader exposure than this opt-in
    implies. Ask for it by name under [commands.jcode] in the global config if
    you want it. Agent state remains opt-in behind --agent-state.

Not planned

  • Per-domain network allowlisting (#107) is closed as out of scope. It is
    achievable rootlessly — a network namespace, slirp4netns or pasta, denied
    direct egress, and a name-aware proxy — but it would put a userspace network
    stack in the path of every packet and force a choice between SNI inspection,
    which stops working the moment SNI is absent or encrypted, and TLS
    interception, which means terminating the agent's credentialed API traffic
    inside ai-jail. A proxy the agent can decline to use is not a restriction,
    which is the same reason --allow-tcp-port fails closed rather than
    pretending. Filter where privilege already exists instead: an nftables rule
    for the agent's uid, a systemd slice with IPAddressAllow=, or a container
    or VM that owns the namespace.

Checksums (SHA256)

6794616ee58f5005cc01011af4e6b7b7db684423d06347b58257850c235ccebc  ai-jail-linux-x86_64.tar.gz
e4d854492c12988a518abf73b69dbe6cee087f787b9551dc223e14c5fe02974f  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.