# Sandbox The sandbox restricts the process to a configurable set of filesystem paths using Linux Landlock. It's opt-in, works in every host (`deft`, `retro`, `retra`), and is enforced by the kernel — a stray `[fs/write]` or file open outside the granted paths simply fails, instead of silently succeeding. Networking is not restricted. Landlock is filesystem-only; the process keeps full network access. ## Enabling Set `DEFT_SANDBOX=1` (or `true`) in the environment: ```bash $ DEFT_SANDBOX=1 deft script.dft $ DEFT_SANDBOX=1 retro ```` Without the variable the sandbox is a no-op. It is also a no-op on non-Linux platforms and on kernels too old for Landlock (kernel 5.13+, see Kernel Support); those cases print a message and continue unsandboxed rather than refusing to start. The sandbox is applied after the prelude and config registry are loaded but before user code runs and before the TUI event loop starts, so all initialisation reads complete first. Application is a one-way door (`landlock_restrict_self`): the process can never widen its own access afterwards. ## Configuration The static path lists live in the project prelude under the `:sandbox` key (see Prelude):
%Prelude{
    :sandbox %{
        :readonly @{ "/etc" "/usr/bin" "/usr/lib" "/usr/lib64" "/usr/share" "/proc" "/sys" }
        :writable @{ "~/.config" "~/.local" }
    }
}
- `:readonly` — paths readable (and executable) but not writable. - `:writable` — paths fully writable: read, write, create, remove. Both lists are optional. A leading `~` is expanded to `$HOME` when the sandbox is applied, so `"~/.config"` grants the subtree beneath the real home directory. `deft init` writes a template `:sandbox` block for you. Edit the lists directly in `.deft/prelude.dft`, or use the `deft sandbox` CLI which edits them for you: ``` $ deft sandbox list # show both lists $ deft sandbox add /srv/data # add read-only $ deft sandbox add ~/code/write-dir -w # add writable $ deft sandbox remove /srv/data ```` See [The `deft` Binary](../08-Tooling/cli) for the full subcommand reference. ## What Is Always Granted A small set of host-essential, environment-derived grants is applied by the runtime itself and cannot be edited away: | Path | Access | Why | |------|--------|-----| | cwd subtree | full | the project the runtime runs in | | `/tmp` | full | temp files, sockets | | `$XDG_RUNTIME_DIR` | rw socket | Wayland/X11 compositor socket | | `$HOME` | read-only | Xauthority, fontconfig cache, config reads | | `/dev`, `/dev/pts` | rw + ioctl | GPU render nodes, input, integrated-terminal PTYs | | `/` | execute-only | absolute-path resolution of binaries | | font path (TUI) | read-only | when the configured font lives outside cwd + `/tmp` | Writable sub-trees like `~/.config` from the `:writable` list union over the read-only `$HOME` rule within the same ruleset, so they become writable without widening the rest of the home directory. ## Semantics and Limits - Directory-granular grants. A rule roots on a directory and covers its subtree. Adding a list entry that names a file is warned about and skipped — add the parent directory instead. - One-way door. After startup the process's filesystem view is fixed for its lifetime. There is no runtime escape hatch. - Filesystem only. Sockets, network, and process signals are unaffected. This is not a full security sandbox — for untrusted code, pair it with `runtime/*` heap isolation (see Runtimes); child runtimes share the process and therefore the same sandbox. - Not a per-app boundary. The sandbox bounds the whole process. All panels in a TUI host and all child runtimes run inside the one set of grants. ## Kernel Support Landlock ABIs are detected automatically and the widest supported set of access rights is used: | ABI | Kernel | Notes | |-----|--------|-------| | v6 | 6.13+ | scoped access | | v4 | 6.7+ | networking field in the ruleset attr | | v3 | 6.2+ | up to `TRUNCATE` | | v2 | 5.19+ | up to `REFER` | | v1 | 5.13+ | baseline: read/write/create/remove/exec | On kernels without Landlock the process prints `sandbox: landlock unavailable (kernel too old)` and continues without restriction. ## Diagnosing Denied operations fail with the usual OS-level errors (`permission` denied`, `no such file or directory` on open), which surface as` normal Deft errors from `fs/*` and `sqlite/*` stdlib functions. Check the startup line `sandbox: active (landlock, cwd + /tmp + prelude paths)` to confirm the sandbox engaged, then add the missing path to the appropriate list: ``` $ deft sandbox list read-only: /etc /usr/bin writable: ~/.config $ deft sandbox add ~/data -w added ~/data (writable) ```` ## See Also - Prelude — the `:sandbox` key lives in `.deft/prelude.dft` - [The `deft` Binary](../08-Tooling/cli) — `deft sandbox` subcommand - Runtimes — heap isolation vs. OS sandboxing