Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
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)

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>

home | help