Secrets of the Founders
"People don't talk that way anymore." — Riley Poole
HTTP proxies (HTTP_PROXY/HTTPS_PROXY env vars) require every tool to opt in. In practice they break constantly:
- Git SSH doesn't use HTTP proxies
- gRPC often ignores proxy vars
- Node.js needs
NODE_OPTIONS=--use-env-proxy(only ≥ 20.18) - npm/yarn have their own proxy config
- Many Rust/Go/C binaries don't read proxy vars at all
If you pair this with seatbelt (deny network*) to force compliance, anything that doesn't speak HTTP proxy protocol just dies.
DYLD interposing works at the connect() syscall level. It doesn't care what protocol the tool speaks — HTTP, gRPC, WebSocket, raw TCP, SSH — they all call connect(). The process doesn't know it's being proxied.
Container-based sandboxes provide strong isolation but can't run native macOS apps. No Xcode, no Finder, no .app bundles, no native GUI tools. File access goes through Docker bind mounts, not your actual filesystem. There's startup overhead from spinning up containers.
sandpit runs in your normal macOS environment. Your agent has the same tools and filesystem you do, just with guardrails. It's the difference between putting the Declaration in a vault vs. putting it behind bulletproof glass — you can still see it, but nobody's stealing it.
sandbox-exec is a SIP-protected binary that strips DYLD_INSERT_LIBRARIES from the child environment. If you launch via sandbox-exec, the DYLD hooks never load. There's no way around this — it's an Apple security measure.
So sandpit picks one: DYLD for binaries that support it (most AI agents via Homebrew), seatbelt as a fallback for platform binaries where DYLD can't work.
On Linux, this problem doesn't exist — bubblewrap doesn't strip LD_PRELOAD, so both layers can run together.
Seatbelt mode is a narrow fallback for kernel-enforced file protection when the target binary is a SIP/hardened platform binary (e.g. /usr/bin/python3). It can't do network filtering or exec argument inspection — those fall through to the adversary LLM reviewer.
For the common case — Homebrew-installed agents like goose, pi, claude, node — DYLD mode gives you full enforcement across all layers. Seatbelt is the backup vault.
The adversary is an LLM that reviews every tool call the agent makes before it executes. It understands context — what you asked for, what the agent is doing — and can catch things that pattern matching misses.
sandpit install <agent> writes your [adversary].rules policy into the agent's config. The mechanistic rules (network domains, exec patterns, file blocks) are enforced by DYLD or seatbelt at runtime — the adversary focuses on higher-level judgment: "is this tool call consistent with the task?"
The adversary matters most when:
- Novel exfiltration patterns not in your block list
- Social engineering via tool calls
- Agents running on binaries where neither DYLD nor seatbelt is available
- Multi-step attacks where individual commands look benign
In the worst case (adversary-only mode), it's the sole defense. Like Ben Gates with just a lemon juice pen and a lighter.
| sandpit | HTTP Proxy | Containers | |
|---|---|---|---|
| Platform | macOS native | macOS/Linux | Linux (Docker) |
| Network | Transparent (connect()) |
Requires opt-in | iptables |
| Breaks tools? | No | Yes | No macOS apps |
| Exec control | Argument-level | Binary-level | Seccomp |
| File control | DYLD/seatbelt | seatbelt/bwrap | Bind mounts |
| Setup | cargo build |
Proxy + config | Docker + K3s |
| LLM review | Built-in ✅ | No | No |
Apple deprecated sandbox-exec in the man page years ago, but it still works on current macOS versions and is actively used by the system itself. Apple's Sandbox framework (SBPL profiles) isn't going anywhere — sandbox-exec is just the CLI interface to it.
sandpit uses it as a fallback only. For most agents, DYLD mode is preferred and seatbelt never enters the picture.
Defense in depth means an agent would have to bypass multiple independent layers:
- DYLD hooks: Userspace hooks can theoretically be bypassed by directly invoking syscalls (skipping libc). This is uncommon in practice — most tools use libc.
- Seatbelt: Kernel-enforced. No userspace bypass possible for file operations.
- Adversary LLM: Could potentially be prompt-injected, but it's a separate model instance with a fixed system prompt and your rules. The agent can't modify the reviewer's instructions.
No sandbox is perfect. sandpit's goal is to make exfiltration hard enough that it's not the path of least resistance. Like the security at the National Archives — not literally impenetrable, but you'd need a very elaborate plan involving lemon juice and a hair dryer.
Not yet, but it's on the roadmap. The architecture maps cleanly:
DYLD_INSERT_LIBRARIES→LD_PRELOAD(same C hooks)sandbox-exec(seatbelt) → bubblewrap (bwrap) with namespaces- Adversary layer → same code, works anywhere
On Linux it's actually better — bubblewrap doesn't strip LD_PRELOAD, so both layers can run simultaneously. And there's no SIP to contend with.
We know. That's why we're here.
"Of all the ideas that became the United States, there's a way to protect every single one of them. I'm not talking about the amendments. I'm talking about sandpit.toml."