Vinícius dos Santos Oliveira builds sandbox support into Emilua, his LuaJIT execution engine, and wrote up the route through a field he describes as mostly uncharted: the pieces you need are scattered across kernel APIs, libc interposition tricks and papers, with no unified map.

He starts from Julien Tinnes and Chris Evans’ definition, and it does the load-bearing work for everything after it. Sandboxing means discretionary privilege dropping — restricting a process’s privileges programmatically, without administrative authority on the machine. That rules out a lot of things people call sandboxes, including sysadmin filesystem permissions, which a program must never be able to rewrite.

The design pattern he lands on is old and well-funded:

  • Credentials live at the process level on every mainstream OS, so compartments are processes.
  • That makes it distributed application development, as the Capsicum researchers put it — components in separate processes communicating by message passing.
  • Emilua exposes three calls for this: spawn_vm, actor.send, inbox.receive. Actors share no memory, never run in parallel with themselves, and can pass each other’s addresses in messages, so topologies are arbitrary.
  • UNIX domain sockets carry the messages, and file descriptors can be sent over them. That turns descriptors into capabilities: files, pipes, sockets, device nodes, memfds, pidfds, eventfds, eBPF programs.
  • It works because UNIX checks permissions when a descriptor is created, not when it is used. Root can open a file and an unprivileged process reading through the inherited descriptor succeeds. The exception is ioctls — even isatty() is one on Linux.

FreeBSD’s Capsicum is the benchmark he keeps returning to. cap_enter() disables ambient authority in one call, after which open and connect fail because the names used to refer to resources simply stop existing; resources can only arrive through the inbox. In the Capsicum paper’s Chromium port, that took 100 lines of code against 11,301 for seccomp, 22,350 for Windows ACLs and 560 for macOS Seatbelt — and the cheaper alternatives did not meaningfully restrict the sandbox.

Linux, in his account, went the other way:

  • Sandboxing first arrived by abusing superuser mechanisms such as a setuid helper configuring a chroot, which arbitrary programs by definition cannot use.
  • User namespaces made it worse. Inside a nested namespace the process is superuser within that namespace, so kernel code paths previously reachable only by root became reachable by everyone, on a decade of code never written for that premise.
  • Namespaces are fine for trusted containerisation tools, but they are a bad interface for software sandboxing — a bet he explicitly recommends against.
  • Seccomp is syscall filtering, and “not a good mechanism for discretionary privilege dropping.” Blacklists break as new syscalls appear and syscall numbers vary across architectures; a filter can be bypassed by running a 32-bit binary on x86-64, or by setting X32_SYSCALL_BIT, which the kernel documentation admits shares the same arch value.
  • Whitelists are what serious projects use, at the cost of arcane per-arch parameter ordering — Docker needs several rules for clone alone.

For code you cannot rewrite, he documents oblivious sandboxing: interpose the libc functions that reach for ambient authority, which works through LD_PRELOAD and even against static libc because libc symbols are weak. Emilua 0.11 exposes this as libc_service, where a small Lua script runs at each intercepted call site and policies become fully dynamic — his Telegram example resolves names only to pluto.web.telegram.org and allows connects only to IPs resolved in earlier steps. Plugins get loaded by descriptor instead of path, since dlopen cannot see the filesystem once ambient authority is gone.

The part worth carrying beyond systems programming is the scepticism. He argues down two threat models in the piece — sandboxing tdlib to defend against Telegram, when you are handing Telegram your data anyway, and hardening initramfs decompression against a user who already controls the initramfs — on the grounds that you should check whether the model makes sense before paying for the sandbox. Every shell should have sandboxes, he argues, and browsers and chat clients are shells: a media-parsing bug in a messenger is access to your whole message history.

The takeaway from the whole essay is that sandboxing is a design problem before it is a kernel feature, and most of the difficulty on Linux comes from not having decided what a capability is. Capsicum decided — which is why the same result takes one call there and a hand-maintained syscall whitelist plus Landlock everywhere else.