cl-exec-sandbox is a policy-driven process sandboxing library for Common
Lisp. Its policy model provides:
- read, write, and deny filesystem rules
- literal paths, deny globs, and portable special roots
- more-specific nested policy overrides
- read-only host and workspace-write presets
- protected project metadata such as
.git - full, isolated, and managed proxy-only network modes
- process, user, IPC, UTS, and network namespace isolation on Linux
- fresh
/procand minimal/devmounts - child timeouts and optionally bounded captured output
- explicit capability discovery
One policy is translated by a per-host backend. A policy a backend cannot
enforce signals sandbox-unavailable naming the missing capability. Query
sandbox-capabilities or sandbox-supported-p before relying on a capability.
The policy surface and Linux enforcement model were checked against OpenAI
Codex commit 2e1607ee2fa8099a233df7437adee5f16a741905. Codex is a reference.
The Linux backend targets x86-64 and SBCL. It uses the system bwrap binary
for filesystem and namespace isolation, plus a private helper for
no_new_privs, seccomp, and managed proxy routing. The helper lives beside
the Lisp sources.
The macOS backend runs commands under Seatbelt through /usr/bin/sandbox-exec,
generating a profile from the same policy. Resolved rules are emitted from the
broadest to the most specific, so Seatbelt’s last-match-wins resolution
reproduces nested overrides and protected metadata. Whole-root rules are
emitted before device access, so a read-only root still permits /dev. A
rule naming a single file becomes a literal filter.
On macOS:
:enabledand:isolatednetworking worksandbox-capabilitiesreports:process-namespacesas false- process separation is an accidental-damage boundary
Deny globs need rg on either host. Seatbelt installations outside /usr/bin
can set CL_EXEC_SANDBOX_SEATBELT to an absolute executable path.
(let ((policy
(cl-exec-sandbox:workspace-write-sandbox-policy
:workspace-roots (list #P"/work/project/")
:network :isolated)))
(cl-exec-sandbox:run-sandboxed
"/bin/sh"
'("-c" "git status --short")
:policy policy
:working-directory #P"/work/project/"
:output-limit 65536
:error-output-limit 65536))When a limit is exceeded, the returned prefix is available through
sandbox-result-output or sandbox-result-error-output. Inspect
sandbox-result-output-truncated-p and
sandbox-result-error-output-truncated-p before presenting captured output.
Build the private Linux helper and run the complete test suite:
./checkSeatbelt profile translation is a pure function of a policy, so its tests run on any host. They assert the generated profile text.
Applications which vendor this system should run scripts/build-helper during
their build and ship build/cl-exec-sandbox-helper beside the Lisp sources.
Set CL_EXEC_SANDBOX_HELPER to an alternate absolute helper path when the
installed layout differs. Packaged Bubblewrap installations outside /usr/bin
and /bin can set CL_EXEC_SANDBOX_BWRAP to its absolute executable path.
Part of the Lambda Symbolics library shelf.