Sandboxing is when a developer limits available system resources to a program from within its own source code. A classic example is calling chroot(2) to change the root file-system to an empty directory so that the program cannot scribble into the root file-system.
int main(void) {
/* Program has full file-system access. */
chroot("/var/empty");
chdir("/");
/* File-system root re-rooted in /var/empty. */
int fd = open("/etc/passwd", O_RDONLY);
/* Tried to open /var/empty/etc/passwd... 🤭 */
}
Operating systems have come a long way since chroot()
,
and allow developers to limit resources far beyond just the
file-system root. In this article, I'll survey some modern tools
for sandboxing and how easy or hard it might be to do so by drawing
from documentation and examples. This is not a research
paper: it's a survey and guide.
We'll cover the main open source operating systems with sandbox tools: Linux, OpenBSD, and FreeBSD (including DragonFlyBSD). Mac OS X gets limited mention, as does Java. If you know of other operating systems with such tools (e.g., NetBSD's secmodel), please raise an issue or a GitHub pull request.
Without further ado: in 2025, with what tools can we limit a program to only already-open file descriptors (e.g., standard IO) and memory management—regular console activities—on these operating systems? If the running program tries to do anything else, it must be terminated or otherwise unable to acquire the requested resources (files, sockets, shared memory, etc.).
print("Hello, world! 👋")
from pathlib import Path
txt = Path(".profile").read_text()
import http.client
connection = http.client.HTTPSConnection("www.bsd.lv")
In the following, I plot the length of a tool's documentation
(manpage
) over the length of an example usage. Why the length of
the manpage? It's the standard way developers interact with tool
documentation; and in a way, measures the cognitive load required to
understand and use the tool.
How hard is it to sandbox your source code?
This graphs the text length of references that must be read to understand the system to the number of lines in an example.
Jump to systems for references and examples.
Systems easy to understand (short references) and implement (short source code) are grouped in the lower-left, while progressively more complicated systems are in the upper-right.
Below is a list of all tools available on our operating systems. Click the folder icon on an example to see its source code, references, and notes. Which method would you choose? Sources readable on a normal mobile phone (<20 lines) have lines show in blue, barely readable (20–30 lines) in orange, and above in red. Deprecated sandboxes are marked next to the subsystem name.
In the above, I've also add wrappers for these systems in different
languages. I don't include library helpers
such as
libseccomp,
since they don't (much) change the cognitive overhead in reading the
canonical documentation. Ultimately, any sandbox tool will be
implemented in the kernel.
We can further clarify this data by grouping by operating systems and sandboxes. How hard it is to implement a sandbox in your environment of choice?
These are all trivial examples, and only demonstrate as much as
Hello, world
programs demonstrate a programming language.
Let's refocus on a real world example taken both as a snapshot and
as developed over time.
Let's use openssh-portable as a canonical example. OpenSSH is under tremendous pressure for its security. It has a number of source code sandboxes, including most of those mentioned in this survey. In general, these sandboxes will do little more than our examples—limit resources used to only communication over standard IO and to perform in-process duties (memory management, etc.). How do the lengths of source code (in lines) for each sandbox measure, with the collected references length for comparison?
This only shows an instantaneous view of the system: part of the security of a system is its maintenance over time. How difficult is it to maintain the security implementations over time? In the following chart, I continue looking at openssh-portable, but extracting its commit history (via GitHub) over time for the specific files used for sandboxing.
This plots cumulative commit counts in the GitHub repository over time. Size of commits is not regarded—only the frequency. Subsystems that require significant maintenance will grow much more quickly than those with lighter maintenance burdens.
In this section, I survey real-world sandbox users in open source systems using one or more sandbox.
This is far from complete! Help make these charts more meaningful: if you've significantly contributed to a sandbox effort, please submit an attestation by a GitHub pull request. Thank you!
For in-house
systems, I mined the
FreeBSD and
OpenBSD git
repositories (specifically usr.bin
and
usr.sbin
) for sandbox invocations, then looked up the
earliest entry for a contributor.
For general open source, I drew from the results of Sandboxing Adoption in Open Source Ecosystems (see the thanks section), which in turn searched third-party software repositories for seccomp (Debian and Fedora) and pledge. I only included those systems that had a specific commit and author for adding the sandbox support.
Lastly, I used GitHub search for key functions used in sandboxing. This was particularly useful for Capsicum and Landlock.
It's clear that OpenBSD's pledge has been massively successful in getting traction in open source, both within OpenBSD and for third-party systems. This is likely due both to how ports are maintained by OpenBSD developers and the ease at which systems can be extended with sandbox support. The documentation and reference examples are succinct and easy to digest.
Linux's seccomp is far more complicated: it has a seven-fold increase in reference complexity, and even more for source complexity, over OpenBSD and FreeBSD. Landlock showed promise as a simpler Linux alternative. The maintenance burden for seccomp, as illustrated by openssh-portable, is considerable.
FreeBSD's Capsicum has fairly good traction within FreeBSD. Like OpenBSD, its documentation and reference examples are easy to digest.
Ominously,
Mac OS X
has deprecated its source sandbox (seatbelt
), as has
Java by discontinuing the
JSM.
I'm starting this site to gain a full picture of the sandbox
landscape in open systems. Having a list of possible combinations
of languages, operating systems, and sandbox tools is a good start.
And for that, if you have additions, please visit the
GitHub
page to add more examples.
More importantly, I want to know who is using these security systems, and where. Let's put together some numbers for how many systems in the wild really are protected, and start a conversation about why systems are more popular, and what we can do to raise the state of security on less-popular systems. You can easily add attestations to systems where you've contributed a security sandbox with a GitHub pull request.
For a scientific treatment of the subject, read Sandboxing Adoption in Open Source Ecosystems, Maysara Alhindi and Joseph Hallett, SESoS 2024. I'd like to thank the authors for making their data available for me to incorporate into the statistics.
I'd also like to thank Ed Maste (emaste), Florian Obser (fobser), and Damien Miller (djmdjm) for their input in the subject matter.