Project status
What is implemented, what was deliberately not built, and what is out of scope. Every gap named here is also in known limitations, with the detail.
Implemented
- Policy that means what it says. Denials survive resolution and are enforced by the isolation layer, which is on by default, by covering the path; unenforceable network rules fail at resolution rather than silently inverting; the target executable is granted implicitly; config discovery covers the working directory as well as the target's; arguments after the target are passed through untouched.
- Config you decided to apply. A
bailey.tomlfound by walking a directory can have arrived with the code being confined, so it contributes only once accepted withbailey trust, recorded against its contents so an edit asks again. Your global config, your own profiles, and--configare unaffected. - The world the target sees. The environment is built rather than inherited, so credentials do not cross unless named. Each target gets a private home that persists, a private
/tmpand/dev/shmunder isolation, and the directory it was invoked from. - Network confinement. A policy that denies egress puts the target in its own network namespace with only loopback, so every protocol fails rather than TCP alone. Landlock scoping keeps host abstract sockets and host processes out of reach on Linux 6.12 and later.
- Audit you can trust. Runs are confined by default, the target is held at
execuntil the recorder is watching, observation is scoped to the run's cgroup, and traces are versioned and say what they lost. - Knowing what happened.
bailey doctorreports what this host can enforce and what each gap costs; every run reports what it enforced and what the host took away. - Knowing what it costs. The overhead is measured rather than asserted, by a script in the repository, and the numbers are published.
- One service at a time. A
[[socket]]relay carries a single desktop socket into the sandbox, so Wayland, the session bus, or audio can be granted without the runtime directory they live in, ssh-agent included. Theurl-openservice brokers a URL to the host browser over one validated line. - FUSE without the mount syscalls. A
[[fuse]]entry runs its mount as the caller and unmounts with the run, so the target uses a FUSE filesystem while the seccomp filter keeps denyingmount(2). A grant whose path cannot be read, as with a dead mount, refuses the run rather than silently dropping the grant. - Grants on the command line.
--allow-read,--allow-write,--allow-exec,--read-only,--deny, and--allow-netform the highest config layer, for one-off access without touching a file. - One TCP port at a time. A
[[forward]]entry carries a host port onto the sandbox's own loopback, so a tool that dials a local daemon reaches it while the network namespace keeps refusing everything else.
Decided against
Each of these was specified, investigated, and dropped.
on_violationhooks. Landlock denies silently, and seeing a denial needs the kernel's audit subsystem enabled at boot as well as permission to read its records. On a kernel with the log made readable but audit disabled, a deliberately triggered denial produced zero records: the hook could never have fired. Removed rather than carried as config that does nothing.bailey auditanswers the same question.
Not planned
- Transparent interception, so that every program launched by a store client is automatically sandboxed. Explicit launcher only.
- BPF-LSM enforcement. It would raise the privilege floor for every run and depend on a kernel config the user cannot change without a reboot.
- X11 nesting. Wayland first.
- Non-Linux platforms.