diff --git a/scripts/README.md b/scripts/README.md index 75bba47..bcc7636 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -208,8 +208,11 @@ Outputs to stdout, making it composable with other pipeline stages. ## x/elevate -Elevation plugin invoked by `execute_code` when a step is marked `elevated: true`. -Runs the command outside the sandbox and returns its output. +Sandbox escape hatch invoked by `execute_code` when a step is marked `elevated: true`. +The Landlock sandbox is enforced at the kernel level — certain operations (filesystem +paths outside the sandbox config, specific syscalls) are simply blocked regardless of +what the code does. `x/elevate` provides a controlled way to run those steps outside +the sandbox entirely, without changing user privileges. ### Interface @@ -225,38 +228,45 @@ script must: - Write combined stdout/stderr to its own stdout - Exit with the command's exit code (non-zero is treated as failure) -That's the entire contract. Any script that satisfies it is a valid elevation backend. +That's the entire contract. Any script that satisfies it is a valid backend. The plugin is looked up in `OLLIE_PLUGINS_PATH` (first colon-separated entry) if set, otherwise in `~/.config/ollie/scripts/x/`. Override via env to use a different location without modifying the installed scripts. +### The constraint + +Because Landlock is kernel-enforced, the backend cannot simply exec the command inside +the sandboxed process — the restrictions apply regardless. The command must reach a +process that was spawned outside of landrun entirely. The only viable pattern is to +forward the command to an external daemon over a socket or pipe, where that daemon runs +in an unsandboxed context and sends the result back. + ### Minimal example -The simplest possible backend — unsandboxed exec, no privilege escalation: +The simplest possible backend — direct exec, no sandbox. Suitable for development or +environments where the sandbox itself is not in use: ```sh #!/bin/sh -# x/elevate: run command outside the sandbox with no additional privileges. +# x/elevate: run command outside the sandbox (no landrun in this environment). shift # drop the '--' exec sh -c "$1" ``` -This is useful for development or environments where the sandbox is the only -restriction that needs lifting. - ### superpowerd example -The default `x/elevate` uses superpowerd as the elevation backend. superpowerd is a -hypothetical privilege broker: it holds a session token, -receives `ExecuteCommand` requests over a Unix socket, and runs them with the -permissions granted to the session. +The default `x/elevate` uses superpowerd as its backend. superpowerd is a hypothetical +external command broker: a daemon running outside any sandbox that receives +`ExecuteCommand` requests over a Unix socket, runs them, and returns the result. This +satisfies the constraint above — the command executes in the daemon's process, which +was never wrapped by landrun. **How it works, step by step:** 1. If `SUPERPOWERD_SESSION_TOKEN` is not in the environment, the script re-execs itself - under `superpowers run-session`, which acquires a token and re-runs the script inside - a privileged session context: + under `superpowers run-session`, which registers a session with the daemon and + re-runs the script with the token set: ```python if "SUPERPOWERD_SESSION_TOKEN" not in os.environ: @@ -288,21 +298,13 @@ permissions granted to the session. 4. The response's `stdout`, `stderr`, and `exit_code` are forwarded back to `execute_code`. - ### Custom backends -Replace `~/.config/ollie/scripts/x/elevate` with any executable that satisfies the -interface. The key constraint: the backend must run the command in a process that was -spawned **outside** the landrun sandbox. Landlock restrictions are enforced at the -kernel level — running `sudo` or `doas` inside a sandboxed process does not escape -them. The only way out is to hand the command to a process that was never wrapped by -landrun in the first place, which is exactly what superpowerd does via its Unix socket. - -The superpowerd pattern (separate privileged daemon, commands sent over a socket) is -the right model for any custom backend. +Any daemon-and-socket design works. The daemon must be running outside landrun; the +`x/elevate` script is the bridge between the sandboxed agent and that daemon. **Disabling elevation:** replace `x/elevate` with a script that exits non-zero. -Steps marked `elevated: true` will then fail rather than run unsandboxed: +Steps marked `elevated: true` will fail rather than escape the sandbox: ```sh #!/bin/sh