# 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](#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)):
 %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](../07-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](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](prelude) — the `:sandbox` key lives in `.deft/prelude.dft` - [The `deft` Binary](../07-Tooling/cli) — `deft sandbox` subcommand - [Runtimes](runtimes) — heap isolation vs. OS sandboxing