“The sandbox-exec command is DEPRECATED. Developers who wish to sandbox an app should instead adopt the App Sandbox feature described in the App Sandbox Design Guide”
MacOS 10.13.6 is from 2017, so this has been deprecated for almost 10 years.
MillionOClock•about 4 hours ago
I wonder how many major applications and tools depend on sandbox-exec today despite that depreciation, IIRC I can think of the Codex CLI and Swift Package Manager.
selridge•about 4 hours ago
Claude, Firefox, safari, chrome, etc etc etc etc
Basically everyone who has to care about security on the Mac.
theowaway213456•about 3 hours ago
Bazel as well.
cpach•about 4 hours ago
Does anyone have any details regarding the deprecation? I wonder why Apple made this decision.
selridge•about 3 hours ago
There’s not that much detail. A few comments in 2019 from a DTS person indicated that Apple didn’t really anticipate people shipping on this in volume. My guess is they want to dissuade people from using it.
They can’t immediately just do away with it because a bunch of their first party apps use it (entitlements don’t cut it). It’s a weird space.
js2•about 2 hours ago
> a DTS person
Quinn the Eskimo, no doubt. I'm convinced he or she is the only actual human being providing developer technical support at Apple. Certainly the only one I've ever successfully communicated with. Support tickets go to robots who are incapable of providing relevant answers. Maybe Quinn is an alias with a team of humans behind it, but I don't think so. I've had him or her take forum posts to private e-mail and it does seem like a single person.
Unfortunately, even Quinn is fully at the mercy of Apple's internal bureaucracy, which is quite formidable.
TingPing•about 3 hours ago
I don’t know if there are problems with this tool, but the App Sandbox is very configurable and every app store app is in one. It doesn’t make sense to maintain two different complex sandboxing solutions.
selridge•about 3 hours ago
That’s not true. Lots of apple’s own first party apps use SBPL to sandbox because the entitlement granularity doesn’t cut it. There’s also lots of apps on the MAS which use temporary-exception SBPL to fully sandbox.
I agree that there is no sense in operating dual systems, but entitlements can’t replace SBPL yet.
jen20•about 3 hours ago
If swift package manager is using it (I believe it is based on some of the error messages I occasionally see from it), deprecating it is difficult, since SPM is not distributed as an App Store app.
bdash•about 2 hours ago
See https://bdash.net.nz/posts/sandboxing-on-macos/ for more details on how sandboxing works on macOS. It touches on how the SBPL Scheme source code is interpreted in userspace to build a bytcode representation of the policy, and the kernel MAC hooks that the Sandbox kernel extension uses for enforcing sandbox policies.
ImJasonH•about 5 hours ago
Both Claude Code and Codex use sandbox-exec with Seatbelt to sandbox execution:
It weirds me out a bit that Claude is able to reach outside the sandbox during a session. According to the docs this is with user consent. I would feed better with a more rigid safety net, which is why I've been explicitly invoking claude with sandbox-exec.
xyzzy_plugh•about 5 hours ago
It drives me nuts that sandbox-exec has "sandbox" in the name, since it's nothing like a real sandbox, and much closer to something like a high-level seccomp, and not much to do with "App Sandboxes" which is a distinct macOS feature.
IMO a real sandbox let's a program act how it wishes without impacting anything outside the sandbox. In reality many of these tools just cause hard failures when attempting to cross the defined boundaries.
It's also poorly documented and IIRC deprecated. I don't know what is supposed to replace it.
If macOS simply had overlay mounts in a sandbox then it would unlock so much. Compared to Linux containers (docker, systemd, bubblewrap, even unshare) macOS is a joke.
m132•about 2 hours ago
> not much to do with "App Sandboxes" which is a distinct macOS feature
The App Sandbox is literally Seatbelt + Cocoa "containers". secinitd translates App Sandbox entitlements into a Seatbelt profile and that is then applied by an libsystem_secinit initializer early in the process initialization, shortly before main(). macOS does no OS-level virtualization.
gobdovan•about 4 hours ago
What you're describing is a resource virtualization with transactional reconciliation instead of program isolation in the mediation sense (MAC/seccomp-style denial).
To let a program act as it wishes, ideally every security-relevant mutable resource must be virtualized instead of filtered. Plus, FS is only one of the things that should be sandboxed. You should also ideally virtualize network state at least, but ideally also process/IPC namespaces and other such systems to prevent leaks.
You need to offer a promotion step after the sandbox is over (or even during running if it's a long-running program) exposing all sandbox's state delta for you to decide selective reconciliation with the host. And you also must account for host-side drift and TOCTOU hazards during validation and application
I'm experimenting with implementing such a sandbox that works cross-system (so no kernel-level namespace primitives) and the amount necessary for late-bound policy injection, if you want user comfort, on top of policy design and synthetic environment presented to the program is hair-pulling.
simonw•about 3 hours ago
Sandbox-exec covers everything I personally expect from a sandbox:
- controls which files the process can read and write
- controls what network access the process is allowed
_wire_•about 5 hours ago
> If macOS simply had overlay mounts in a sandbox then it would unlock so much. Compared to Linux containers (docker, systemd, bubblewrap, even unshare) macOS is a joke.
You'll want to look into Homebrew (or Macports) for access to the larger world
TingPing•about 3 hours ago
They are discussing a Linux kernel feature. Docker/Podman on macOS launch a virtual machine to function.
ksherlock•about 4 hours ago
alias sandbox-no-network='sandbox-exec -p "(version 1)(allow default)(deny network*)"'
pro-tip on alias:
for sh-compliant shells, including a whitespace at the end of the alias string causes the next token to also go through alias expansion. (maybe it would also be a hint to the shell for tab completion as well). This is a perfect example of when, where, and why you would want to do that.
davidcann•about 5 hours ago
I made a UI for this to run terminal apps, like claude and codex: https://multitui.com
e1g•about 5 hours ago
I like this! I built something similar for sandboxing CLI agents, and in the repo have a collection of minimal profiles for sandbox-exec to use - https://agent-safehouse.dev/
Tiberium•about 4 hours ago
Codex already uses sandbox-exec on macOS :)
hmokiguess•about 5 hours ago
I’m impressed really neat work! Why did you opt for closed source?
edit: I don’t have a problem with closed source, but when software is expected to be accountable for my security I get a little paranoid, so was curious about the safety and guarantees here. The UX and everything else looks great
ithkuil•about 4 hours ago
Which terminal do you embed?
kilroy123•about 5 hours ago
Wow, this looks very nice.
lyaocean•about 5 hours ago
I'd add one warning for folks who haven't used it before: a tiny typo in the profile can turn into confusing runtime failures later, far away from the command that triggered them. The tool is useful, but the feedback loop is rough.
CGamesPlay•about 5 hours ago
Thanks for putting this together, it's very helpful.
You can spoof or disappear a mashed file.
You can trigger vulnerabilities by breaking internal assumptions of a program.
throw0101c•about 5 hours ago
Do any of the third-party package managers (Brew, MacPorts) perhaps use this for things like builds (or even installs, if things are restricted to (e.g.) /opt)?
Homebrew uses sandbox-exec during builds and installs, yeah. To my memory we’ve used it for at least 6 or 7 years, probably longer.
cwicklein•about 5 hours ago
I’ve written a personal system in Common Lisp for building third-party software on macOS (coincidentally somewhat similar to GUIX), and I use sandbox-exec to isolate execution so that only intended requisites affect the build process and so that installation is strictly confined to the configured destination directory, no scribbling outside the lines.
I think Bazel uses sandbox-exec on macOS.
Advertisement
simonw•about 3 hours ago
If Apple wanted to win back some serous credibility in the AI field there are two very low hanging fruit that they could use:
- Announce that they are no longer going to deprecate sandbox-exec and instead publish detailed documentation for it
- Add a reliable "select all" option to the iOS copy/paste menu
chmaynard•about 5 hours ago
Nice write-up! This is one component of a much larger umbrella framework for security on Apple platforms:
I went down the sandbox-exec rabbit hole recently trying to get a “safe shell” for poking at random GitHub projects. I eventually realized I was solving the wrong problem.
For development you usually don’t need a kernel policy language - you mostly want:
1. builds not trashing your real $HOME
2. no dotfiles/config pollution
3. some basic separation if a project does something dumb
A much simpler (and more reliable) alternative on macOS is just a dedicated throwaway user account. macOS already isolates home directories, keychains, and app state per-user, so you get a practical sandbox without fighting SBPL quirks or mysterious denials.
My workflow now: I have a user called rsh. I clone and build everything there. My real home directory stays clean. If a project goes crazy, it only damages /Users/rsh
It also avoids the “1000 hidden files in your home folder” problem that a lot of language ecosystems cause.
After that I just run rsh, clone repos into ~/projects, and build there.
mixtureoftakes•about 3 hours ago
what is with the ai written articles lately? and ai designed websites?
who looks at it and goes "yes, ill upvote this. more people should see it."?
selridge•about 3 hours ago
This content was from a year ago and was not written by AI.
tonymet•about 2 hours ago
You can tell MacOS was developed by OS nerds but stifled by product managers. There are a lot of gems like Sandboxing and Hyperkit with incredible features and practically no user interface.
kermatt•about 5 hours ago
Interesting config used a Scheme-like format. Any ideas on how that came to be?
comex•about 4 hours ago
Technically, it’s not just Scheme-like but literally a Scheme interpreter (TinyScheme). However, the Scheme isn’t being executed to make individual sandboxing decisions. It’s just executed once while parsing the config, to build up a binary sandbox definition which is what the kernel ultimately uses to make decisions (using a much more limited-purpose, non-Turing-complete execution engine).
selridge•about 3 hours ago
Do we know that engine is not Turing-complete for sure?
cwicklein•about 5 hours ago
I believe GUIX is implemented in Scheme which makes Scheme a natural choice for expressing configuration. Lisp tend to be a natural configuration format for anything written in Lisp. Highly functional configuration processing comes practically for free.
epistasis•about 5 hours ago
I was given trauma from my decades of ELisp configuration for emacs...
Writing a parser for Lisp S-expressions is dead-simple, I wonder if that's why they used the format.
chaostheory•about 4 hours ago
Are sandbox-exec and seatbelt no longer deprecated? I genuinely don’t know. I am asking
selridge•about 4 hours ago
Still deprecated. Still in use by everyone.
blahgeek•about 4 hours ago
Although macOS do provide many little known useful tools (besides this, there’s also dtrace, pf, etc), I still run a Linux VM in my MacBook for daily work. Thing is, the effort I spend on learning these tools is almost wasteful unless I’m doing iOS or macOS development. Skills about Linux tools however, is something people considered valuable because of its wider application. I think apple is missing opportunities by not doing more about macOS Server platform.
Discussion (61 Comments)
“The sandbox-exec command is DEPRECATED. Developers who wish to sandbox an app should instead adopt the App Sandbox feature described in the App Sandbox Design Guide”
That still is the case for MacOS 26.3 (https://man.freebsd.org/cgi/man.cgi?query=sandbox-exec&aprop...)
MacOS 10.13.6 is from 2017, so this has been deprecated for almost 10 years.
Basically everyone who has to care about security on the Mac.
They can’t immediately just do away with it because a bunch of their first party apps use it (entitlements don’t cut it). It’s a weird space.
Quinn the Eskimo, no doubt. I'm convinced he or she is the only actual human being providing developer technical support at Apple. Certainly the only one I've ever successfully communicated with. Support tickets go to robots who are incapable of providing relevant answers. Maybe Quinn is an alias with a team of humans behind it, but I don't think so. I've had him or her take forum posts to private e-mail and it does seem like a single person.
Unfortunately, even Quinn is fully at the mercy of Apple's internal bureaucracy, which is quite formidable.
I agree that there is no sense in operating dual systems, but entitlements can’t replace SBPL yet.
- https://developers.openai.com/codex/security/#os-level-sandb...
- https://code.claude.com/docs/en/sandboxing
IMO a real sandbox let's a program act how it wishes without impacting anything outside the sandbox. In reality many of these tools just cause hard failures when attempting to cross the defined boundaries.
It's also poorly documented and IIRC deprecated. I don't know what is supposed to replace it.
If macOS simply had overlay mounts in a sandbox then it would unlock so much. Compared to Linux containers (docker, systemd, bubblewrap, even unshare) macOS is a joke.
The App Sandbox is literally Seatbelt + Cocoa "containers". secinitd translates App Sandbox entitlements into a Seatbelt profile and that is then applied by an libsystem_secinit initializer early in the process initialization, shortly before main(). macOS does no OS-level virtualization.
To let a program act as it wishes, ideally every security-relevant mutable resource must be virtualized instead of filtered. Plus, FS is only one of the things that should be sandboxed. You should also ideally virtualize network state at least, but ideally also process/IPC namespaces and other such systems to prevent leaks.
You need to offer a promotion step after the sandbox is over (or even during running if it's a long-running program) exposing all sandbox's state delta for you to decide selective reconciliation with the host. And you also must account for host-side drift and TOCTOU hazards during validation and application
I'm experimenting with implementing such a sandbox that works cross-system (so no kernel-level namespace primitives) and the amount necessary for late-bound policy injection, if you want user comfort, on top of policy design and synthetic environment presented to the program is hair-pulling.
- controls which files the process can read and write
- controls what network access the process is allowed
You'll want to look into Homebrew (or Macports) for access to the larger world
for sh-compliant shells, including a whitespace at the end of the alias string causes the next token to also go through alias expansion. (maybe it would also be a hint to the shell for tab completion as well). This is a perfect example of when, where, and why you would want to do that.
edit: I don’t have a problem with closed source, but when software is expected to be accountable for my security I get a little paranoid, so was curious about the safety and guarantees here. The UX and everything else looks great
Readers may also be interested in <https://github.com/eugene1g/agent-safehouse> which was open sourced after a recent HN conversation <https://news.ycombinator.com/item?id=46923436>.
https://github.com/obra/packnplay
https://github.com/strongdm/leash
https://github.com/lynaghk/vibe
(I've been collecting different tools for sandboxing coding agents)
https://github.com/eugene1g/agent-safehouse via CGamesPlay
https://multitui.com/ via davidcann
- https://github.com/jingkaihe/matchlock
- https://github.com/mishushakov/libkrun-go
- https://github.com/earendil-works/gondolin
- https://github.com/butter-dot-dev/bvisor
- https://github.com/amlalabs/amla-sandbox
- https://github.com/eryx-org/eryx
- https://github.com/containers/bubblewrap (not new)
- https://github.com/coplane/localsandbox
- https://github.com/sd2k/conch
- https://github.com/Gerharddc/litterbox
- https://github.com/finbarr/yolobox
- https://github.com/coventry/sandbox-codex
- https://github.com/osks/ctenv
- https://github.com/tianon/gosu
- https://github.com/colony-2/shai
- https://github.com/rcarmo/agentbox
- https://github.com/coder/httpjail
- https://github.com/bytecodealliance/componentize-py
- https://github.com/tursodatabase/agentfs
- https://github.com/always-further/nono
- (another list on HN Deno Sandbox: https://news.ycombinator.com/item?id=46876022)
- Did not check if any/all of these are here: https://github.com/arjan/awesome-agent-sandboxes
You can spoof or disappear a mashed file. You can trigger vulnerabilities by breaking internal assumptions of a program.
I think Bazel uses sandbox-exec on macOS.
- Announce that they are no longer going to deprecate sandbox-exec and instead publish detailed documentation for it
- Add a reliable "select all" option to the iOS copy/paste menu
https://developer.apple.com/documentation/security
For development you usually don’t need a kernel policy language - you mostly want: 1. builds not trashing your real $HOME 2. no dotfiles/config pollution 3. some basic separation if a project does something dumb
A much simpler (and more reliable) alternative on macOS is just a dedicated throwaway user account. macOS already isolates home directories, keychains, and app state per-user, so you get a practical sandbox without fighting SBPL quirks or mysterious denials.
My workflow now: I have a user called rsh. I clone and build everything there. My real home directory stays clean. If a project goes crazy, it only damages /Users/rsh
It also avoids the “1000 hidden files in your home folder” problem that a lot of language ecosystems cause.
Minimal setup :
sudo sysadminctl -addUser rsh -password $(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 16); sudo dseditgroup -o edit -d rsh -t user admin || true; sudo install -d -m 755 -o rsh -g staff /Users/rsh/projects
Then add this alias to your ~/.zshrc command:
alias rsh='sudo -iu rsh /bin/zsh -l'
After that I just run rsh, clone repos into ~/projects, and build there.
who looks at it and goes "yes, ill upvote this. more people should see it."?
Writing a parser for Lisp S-expressions is dead-simple, I wonder if that's why they used the format.