FreeBSD Manual Pages
BOXRUN(1) General Commands Manual BOXRUN(1) NAME boxrun -- sandboxed command execution using FreeBSD jails SYNOPSIS boxrun [options] -- command [args ...] DESCRIPTION The boxrun utility executes a command inside a sandboxed environment using FreeBSD jails, nullfs mounts, and RCTL resource controls. It provides fine-grained control over filesystem visibility, network ac- cess, resource limits, and process security features. The boxrun utility can be installed setuid root, allowing unprivileged users to create sandboxes. Privileges are dropped to the calling user's identity before executing the sandboxed command. The dynamic linker directories /lib and /libexec are always mounted read-only automatically, as they are required for any dynamically linked binary to execute. The linker hints file /var/run/ld-elf.so.hints is also automatically provisioned when library directories are mounted, ensuring the dynamic linker can locate shared objects. OPTIONS Filesystem Options --bind dir Bind-mount dir at the same path inside the sandbox (read-only). --ro-bind dir Alias for --bind (explicit read-only). --rw-bind dir Bind-mount dir at the same path inside the sandbox (read- write). Requires confirmation or -y. --bind-dir src dst Bind-mount src at dst inside the sandbox (read-only). --ro-bind-dir src dst Alias for --bind-dir (explicit read-only). --rw-bind-dir src dst Bind-mount src at dst inside the sandbox (read-write). Re- quires confirmation or -y. --bin Mount /bin read-only. --sbin Mount /sbin read-only. --usr-bin Mount /usr/bin read-only (implies --libs). --usr-sbin Mount /usr/sbin read-only (implies --libs). --usr-include Mount /usr/include read-only. --usr-share Mount /usr/share read-only. --local-bin Mount /usr/local/bin read-only (implies --libs). --local-sbin Mount /usr/local/sbin read-only (implies --libs). --local-include Mount /usr/local/include read-only. --local-share Mount /usr/local/share read-only. --local-etc Mount /usr/local/etc read-only. --libs Mount all standard shared library directories read-only: /lib, /libexec, /usr/lib, /usr/lib32, /usr/libdata, /usr/libexec, /usr/local/lib, /usr/local/lib32, /usr/local/libdata, /usr/local/libexec. Non-existent paths are skipped. --usr Mount /usr/bin, /usr/sbin, /usr/include, /usr/share read-only. Implies --libs. --usrlocal Mount /usr/local/bin, /usr/local/sbin, /usr/local/include, /usr/local/share, /usr/local/etc read-only. Implies --libs. --system Mount /bin, /sbin and all --usr directories read-only. Implies --libs. --all Mount --system and --usrlocal (all standard directories), plus /etc and /var read-only. --etc Mount /etc read-only. --rw-etc Mount /etc read-write. --var Mount /var read-only. --rw-var Mount /var read-write. --tmp Mount a tmpfs at /tmp (writable, 1777). --rw-tmp Alias for --tmp. --tmpfs dst [size] Mount a tmpfs filesystem at dst. An optional size argument may be specified (e.g., "64M"). The tmpfs is created with mode 1777 (world-writable, sticky). --dev Mount devfs at /dev inside the sandbox. --proc Mount procfs at /proc inside the sandbox. --linproc Mount linprocfs at /compat/linux/proc inside the sandbox. --base-path dir Prefix all source paths for --bind, --ro-bind, --rw-bind, and --ov-bind with dir. The destination path inside the sandbox remains unchanged. This does not affect shortcut options like --system or --libs. Useful for running Linux binaries from /compat/linux. Mounting / is not allowed; directories must be specified individually. Library directories are always forced read-only even when specified with --bind. Overlay Options Overlay mounts appear fully writable to the sandboxed process, but changes are stored in a tmpfs layer and discarded on exit unless saved. --ov-bind dir Overlay dir using nullfs read-only plus a unionfs tmpfs upper layer. --ov-bind-dir src dst Overlay src at dst. --ov-system Overlay all system directories (/bin, /sbin, /usr/*), libs. --ov-all Overlay everything (system + usrlocal + /etc + /var). --ov-save file.tgz On exit, save modified and created files from all overlay lay- ers into the specified tar.gz archive. Deletions are not recorded. Negation Flags These subtract features implied by --system or --all: --no-dev Disable devfs even if implied. --no-proc Disable procfs. --no-linproc Disable linprocfs. --no-tmp Disable /tmp tmpfs. --no-libs Remove all library directory mounts. Conflicting pairs (e.g., --dev --no-dev) produce an error. Network Options --allow-net Allow network access inside the sandbox (alias: --net). IP networking is inherited from the host. When enabled and /etc is not bound into the sandbox, /etc/resolv.conf is automati- cally provisioned for DNS resolution. --no-net Deny all network access (default). NAT / Isolated Networking When PF is enabled with the "boxrun" anchor configured, boxrun can pro- vide network-isolated jails with NAT for egress and port forwarding for ingress. Without --nat, --allow-net gives the jail direct access to the host's network stack ("ip4=inherit"). With --nat, each jail gets a private IP address on a dedicated loopback interface and PF handles NAT and port forwarding. --nat Enable NAT mode. The jail receives a private IP from the boxrun subnet and egress traffic is NATed through the host's default route interface. Implies --allow-net. Requires PF with "boxrun" anchor and the boxrun loopback interface (see --create-interfaces). --expose [iface:]hostport:jailport[/proto] Forward traffic arriving on hostport to jailport inside the jail. An optional iface restricts the redirect to a specific network interface. The optional proto is either "tcp" (de- fault) or "udp". Implies --nat. Examples: 8080:80 All interfaces, host port 8080 to jail port 80 (TCP). lo0:2200:22 Localhost only, host port 2200 to jail port 22. em0:53:53/udp Interface em0, UDP port 53. --nat-if interface Override the boxrun loopback interface name. Can also be set via the BOXRUN_LOOPBACK environment variable. --nat-subnet subnet Override the NAT subnet. Can also be set via the BOXRUN_NAT_SUBNET environment variable. --nat-egress interface Override the egress interface used for NAT. By default, the interface of the default route is used. Can also be set via the BOXRUN_NAT_EGRESS environment variable. --create-interfaces One-time setup command: create a cloned loopback interface with the boxrun subnet and description tag. Always requires inter- active confirmation (ignores -y). The interface is auto-de- tected by its description; no hardcoded name is needed. Environment Options --clearenv Clear all environment variables before executing the command (default). The TERM variable is always passed through automat- ically to ensure correct terminal handling. --inherit-env Inherit all environment variables from the parent process. --setenv var value Set the environment variable var to value. --passenv var Pass through the environment variable var from the parent envi- ronment. Resource Limits Resource limits are enforced using RCTL and require kern.racct.enable=1. --limit-mem size Memory limit. Supports K, M, G suffixes. --limit-cpu pct CPU percentage limit (e.g., 50 for 50%). --limit-cputime seconds CPU time limit in seconds. --limit-walltime seconds Wall-clock time limit in seconds. The sandboxed process is killed with SIGKILL when the limit expires. --limit-procs n Maximum number of processes. --limit-fds n Maximum number of open file descriptors. --limit-read-bps n Read bandwidth limit (supports K, M, G suffixes). --limit-write-bps n Write bandwidth limit (supports K, M, G suffixes). --limit-read-iops n Read IOPS limit. --limit-write-iops n Write IOPS limit. Security Options All security hardening is enabled by default. Use the --allow-* flags to relax specific restrictions. --secure No-op; kept for backward compatibility. All hardening is now enabled by default. --ptrace Allow ptrace and debugging of processes inside the sandbox (alias: --allow-ptrace). --no-ptrace Deny ptrace and debugging (default). --aslr Force Address Space Layout Randomization (ASLR) enabled (de- fault). --no-aslr Force ASLR disabled for the sandboxed process. --no-new-privs Ignore set-user-ID and set-group-ID bits on executables within the sandbox (default). Prevents privilege escalation via se- tuid binaries. --protmax Enforce implicit mmap(2) PROT_MAX protection (default). Pre- vents mappings from being upgraded to permissions beyond what was requested. --no-protmax Disable implicit PROT_MAX enforcement. --no-wx Disallow creation of memory mappings that are simultaneously writable and executable (W^X enforcement, default). --wx-allow Allow creation of simultaneously writable and executable map- pings (alias: --allow-wx). Required for JIT compilers. --stackgap Force stack gap guard pages enabled (default). --no-stackgap Disable stack gap guard pages. --allow-raw-sockets Allow raw socket creation (required for ping(8)). --allow-chflags Allow chflags(2) inside the sandbox. --allow-mlock Allow mlock(2) inside the sandbox. --allow-mount Allow mounting filesystems inside the sandbox. --allow-set-hostname Allow changing the hostname inside the sandbox. --allow-sysvipc Allow SysV IPC (shared memory, semaphores, message queues). --allow-quotas Allow filesystem quota manipulation. --allow-reserved-ports Allow binding to privileged ports (< 1024). --allow-read-msgbuf Allow reading the kernel message buffer. --allow-nested-jails Allow creating child jails inside the sandbox. --allow-suser Allow superuser privileges for root inside the jail. By de- fault, UID 0 inside the sandbox has no superuser powers ("allow.suser=false"), preventing privilege escalation even if root is somehow obtained. This flag re-enables superuser priv- ileges and is required for operations like raw sockets (ping(8)), binding privileged ports, or changing the hostname. --securelevel n Set the jail's security(7) securelevel to n (valid range: 0-3). The default is 3 (network secure mode), which prevents modifi- cation of firewall rules, raw disk writes, kernel module load- ing, and time changes. Lower values relax restrictions: 0 Insecure mode (no restrictions). 1 Secure mode (no kernel modules, no /dev/mem, immutable flags enforced). 2 Highly secure (level 1 + no raw disk writes, time limited to +-1s). 3 Network secure (level 2 + no firewall rule changes). Identity Options --uid user Run the sandboxed command as the specified user. Accepts a username or numeric UID. --gid group Run the sandboxed command as the specified group. Accepts a group name or numeric GID. --hostname name Set the hostname inside the sandbox. Other Options --clean Remove stale sandbox artifacts left behind by crashed or killed boxrun processes. This scans for leftover mounts under /tmp/boxrun.*, active jails named "boxrun_*", stale PF anchor rules, stale IP aliases, and residual directories. The boxrun loopback interface is not destroyed; use --teardown for that. No sandbox is created; the program exits after cleanup. --teardown Destroy the boxrun loopback interface (the inverse of --create-interfaces). This does not remove jails or mounts; run --clean first if needed. --show Display the effective sandbox configuration (mounts, security settings, resource limits) and exit without running the com- mand. Does not require root privileges. -y Suppress the interactive confirmation prompt. Required for non-interactive use. --help Show a short help summary. --longhelp Show the full option list. --version Show the version number. EXAMPLES Run ls(1) with minimal filesystem and no network: boxrun --bin --dev --no-net -- /bin/ls /bin Run a shell with full base system access and network: boxrun --system --dev --net --bind /tmp -- /bin/sh Run a build with writable output directory (all hardening is default): boxrun --all --dev --bind-dir /home/user/obj /obj \ --ro-bind-dir /home/user/src /src -- make -C /src OBJDIR=/obj Run with resource limits: boxrun --system --dev --limit-mem 512M --limit-walltime 60 \ --limit-fds 64 -- /usr/bin/myapp Run as a different user with clean environment: boxrun --all --dev --uid nobody --gid nobody --clearenv \ --setenv PATH /bin:/usr/bin -- /usr/bin/id Run a Linux binary using the /compat/linux tree (installed via "pkg install linux-rl9"): boxrun -y --base-path /compat/linux \ --bind /bin --bind /lib64 --bind /usr --bind /etc \ --no-libs --dev -- /bin/cat /etc/os-release This mounts /compat/linux/bin at /bin, /compat/linux/lib64 at /lib64, etc., allowing Linux ELF binaries to execute inside the sandbox. The --no-libs flag suppresses automatic mounting of FreeBSD library direc- tories. Run a web server in an isolated NAT jail, exposing port 8080 on the host: boxrun -y --system --dev --nat --expose 8080:80 \ --allow-suser -- /usr/sbin/httpd -DFOREGROUND Run with NAT egress only (no exposed ports): boxrun -y --system --dev --nat -- /usr/bin/fetch -o /tmp/file \ http://example.com/data.tar.gz SECURITY When installed setuid root, the boxrun utility saves the calling user's real UID and GID, elevates to root for jail creation and mount opera- tions, then drops privileges back to the caller's identity before exe- cuting the sandboxed command. All security hardening is enabled by default: network denied, ptrace denied, ASLR forced, no-new-privs, PROT_MAX enforcement, W^X enforce- ment, stack gap enabled, mounting denied, SysV IPC denied, hostname changes denied, nested jails denied, reserved ports denied, kernel mes- sage buffer access denied, superuser disabled inside jail (allow.suser=false), and securelevel set to 3 (network secure mode). Use --allow-* flags to selectively relax restrictions as needed. Library directories (under /lib, /libexec, /usr/lib, /usr/local/lib) are always forced read-only regardless of whether --bind or --ro-bind is used. REQUIREMENTS • Root privileges (or setuid root installation). • kern.racct.enable=1 in /boot/loader.conf for RCTL resource limits. • The nullfs(5) filesystem must be available (loaded by default on FreeBSD). NAT SETUP To use --nat or --expose, a loopback interface with the boxrun subnet must exist and pf(4) must be running with the appropriate anchors. One-time interface creation boxrun --create-interfaces Persist across reboots Add the following to /etc/rc.conf: cloned_interfaces="lo1" ifconfig_lo1="inet 10.235.0.0/16 description boxrun up" pf_enable="YES" pf_rules="/etc/pf.conf" PF configuration Ensure /etc/pf.conf contains the boxrun anchors: nat-anchor "boxrun/*" rdr-anchor "boxrun/*" anchor "boxrun/*" A sample configuration is installed at /usr/local/share/boxrun/pf.conf.sample. FILES /tmp/boxrun.* Sandbox root directories (cleaned by --clean). /var/run/boxrun.ip Tracks allocated IP addresses for NAT jails. /usr/local/share/boxrun/pf.conf.sample Sample pf.conf(5) with the re- quired boxrun anchors. EXIT STATUS The boxrun utility exits with the exit status of the sandboxed command. If the command is killed by a signal (e.g., due to --limit-walltime), the exit status is 128 + signal number (e.g., 137 for SIGKILL). If boxrun itself encounters an error, it exits with one of the sysexits(3) codes: 64 (EX_USAGE) Invalid command-line arguments. 71 (EX_OSERR) System call failure. 77 (EX_NOPERM) Insufficient privileges. SEE ALSO jail(2), jail(8), mount_nullfs(8), nmount(2), procctl(2), rctl(8) HISTORY The boxrun utility was written as a means to quickly run applications in a sandboxed environment without the need to fully install a jail. It reuses the operating system's existing files and limits access using FreeBSD's native security primitives. AUTHORS Tiago Espinha Gasiba FreeBSD ports 15.quarterly May 19, 2026 BOXRUN(1)
NAME | SYNOPSIS | DESCRIPTION | OPTIONS | EXAMPLES | SECURITY | REQUIREMENTS | NAT SETUP | FILES | EXIT STATUS | SEE ALSO | HISTORY | AUTHORS
Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=boxrun&sektion=1&manpath=FreeBSD+Ports+15.1.quarterly>
