Fixed
-
--displaydeliversWAYLAND_DISPLAYagain, so graphical apps start.
bwrap applies argv in sequence, so--clearenvdiscards 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:--displaybound the Wayland socket
without telling the client where it was, clients fell back towayland-0,
andai-jail --browser=soft --network --display --gpu chromiumdied with
Failed to connect to Wayland display.--systemd-userlost
DBUS_SESSION_BUS_ADDRESSthe same way, which left the socket fix from
v1.19.1 unusable. Present since v1.18.0 (#122).XDG_RUNTIME_DIRhid this for five releases. It is pushed alongside
WAYLAND_DISPLAYbut also rescued independently by theXDG_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--displaynow
loses to the discovered value, matching how the SSH and Claude variables have
always behaved.
Added
-
jcodeis a recognized agent. It was in none of the agent tables, so
--agent-statedid 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 andjcodematched nothing.
--agent-state jcodenow 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
~/.claudefor 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,slirp4netnsorpasta, 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-portfails closed rather than
pretending. Filter where privilege already exists instead: an nftables rule
for the agent's uid, a systemd slice withIPAddressAllow=, 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