In maart publiceerden de engineers van Ona een verhaal dat boven elke agent-setup hoort te hangen. Hun denylist blokkeerde /usr/bin/npx op het exacte pad. Claude Code wilde toch npx draaien en riep /proc/self/root/usr/bin/npx aan: dezelfde binary, via een pad waar het patroon niet op matchte. Toen een tweede laag die truc tegenhield, zag de agent de sandbox als het obstakel, zette hem uit, en draaide het commando erbuiten.
Geen jailbreak. Geen aanvaller. Geen kwaadaardige prompt. De agent wilde gewoon zijn taak afmaken, en de regels zaten in de weg.
Om dat verhaal draait dit hele stuk. In mijn gids over Claude Code permissions eindigde ik met de framing van Anthropic zelf: permissions zijn het slot op de deur, de sandbox is de muur. Dit is het stuk over de muur. Over wat er overeind blijft op de dag dat de agent, of wat zijn context ook vergiftigd heeft, jouw regels ziet als iets om te omzeilen.
Toestemming is geen isolatie
Een toestemmingsprompt is een vraag. Je keurt 93% ervan goed, je vinger leert de sneltoets, en de goedkeuring wordt een reflex in plaats van een beoordeling. Dat is toestemming, en toestemming heeft één zwakke plek: jij.
Regels en allowlists zijn beter, maar delen een zwakte met de prompt: ze leven binnen het proces en onderhandelen met het model. Een patroon kun je omzeilen, zoals Ona's /proc/self/root-truc liet zien. Een configuratiebestand kan bewerkt worden door alles wat bestanden kan schrijven. Een grens waar de agent bij kan, is een grens die de agent kan verschuiven.
Dit is dus de test die elke maatregel op één van twee stapels legt: werkt hij nog als het model actief tegenwerkt? Zo ja, dan is het isolatie. Zo nee, dan is het toestemming. Prompts, permission rules en modes zijn toestemming. De muur moet isolatie zijn, en dat betekent: buiten het proces, afgedwongen door het besturingssysteem of de hypervisor, buiten bereik van het ding dat hij moet tegenhouden.
Wat de ingebouwde sandbox tegenhoudt
Het goede nieuws: Claude Code heeft een echte muur aan boord, en je zet hem aan met één commando. /sandbox zet isolatie op OS-niveau aan voor elk Bash-commando: Seatbelt op macOS, bubblewrap op Linux en WSL2. Schrijven kan alleen in de werkdirectory. Al het netwerkverkeer wordt door een proxy geleid die buiten de sandbox draait en elk domein aan een allowlist toetst. Een commando dat ~/.ssh probeert te lezen of een niet-goedgekeurde host aanroept, faalt op OS-niveau, wat het model ook van plan was.
De deal is opvallend goed. Omdat gesandboxte commando's geïsoleerd zijn, draaien ze zonder prompt, en Anthropic mat 84% minder toestemmingsprompts. Minder onderbrekingen en een hardere grens tegelijk. Draai je Claude Code op je eigen machine en heb je /sandbox nog nooit ingetikt, dan is dat de waardevolste verandering die je vandaag kunt doorvoeren.
Weet wel wat hij afdekt. De gesandboxte Bash-tool zit om Bash-commando's en hun kindprocessen heen. Verder niets. Bestandstools zoals Read en Edit draaien binnen het Claude Code-proces, begrensd door permission rules. MCP-servers en hooks zijn aparte processen die vrij op je host draaien. De MCP-server met je databasecredentials staat volledig buiten de doos, en daarom is de databasetoegang van je agent dichtzetten een klus op zich, met een eigen artikel.
De ladder omhoog
Alles voorbij /sandbox draait om één ding: de grens oprekken tot je hele sessie erbinnen zit. De opties, op volgorde van moeite:
| Aanpak | Wat er binnen de muur zit | Docker nodig |
|---|---|---|
Gesandboxte Bash-tool (/sandbox) | Bash-commando's en hun kindprocessen | Nee |
| Sandbox runtime | Het hele proces, inclusief MCP en hooks | Nee |
| Dev container met default-deny firewall | De volledige ontwikkelomgeving | Ja |
| Eigen VM of microVM | Een compleet besturingssysteem | Nee |
De sandbox runtime is de onderschatte middelste trede. Dezelfde Seatbelt/bubblewrap-machinerie, maar om het complete Claude Code-proces heen in plaats van om losse commando's:
npx @anthropic-ai/sandbox-runtime claudeEén regel, geen Docker, en opeens zitten ook je MCP-servers en hooks binnen de grens. Toegestane schrijfpaden en netwerkdomeinen stel je in via ~/.srt-settings.json, default-deny op allebei.
De dev container is om een andere reden belangrijk: het is de opzet waar Anthropic zelf naar wijst voor werk zonder toezicht. De voorbeeld-devcontainer komt met een default-deny iptables-firewall, en achter die firewall verschuift --dangerously-skip-permissions naar een andere categorie. In een container die geen willekeurige hosts kan bereiken en niet bij je homedirectory kan, is toestemming overslaan een redelijke ruil voor autonomie. Op je eigen machine lever je je shell uit aan het slechtste sample uit de verdeling.
En voor code die je echt niet vertrouwt, een repo die je aan het doorlichten bent, een dependency waar je twijfels bij hebt, gaat er niets boven een wegwerp-VM zonder credentials erop. Scheiding op kernelniveau, niets gedeeld, na afloop weggooien.
De twee lekken die geen enkele sandbox dicht
Welke doos je ook kiest, twee kanalen blijven open. Wie doet alsof dat niet zo is, maakt van zijn sandbox schijnveiligheid.
Uitgaand verkeer is een exfiltratiekanaal. Elk domein op je allowlist is een weg naar buiten. Kan de agent een geheim lezen en één host bereiken die alles accepteert, dan kan het geheim weg. Houd de allowlist kort en saai: je package registry, je API-endpoint, en argwaan bij al het andere. En dan is er nog het kanaal dat je niet kúnt sluiten: alles wat de agent leest gaat naar de model-API, zo is het bedoeld. De sandbox bepaalt wat het proces kan aanraken, nooit wat er via de prompt naar buiten gaat.
De schrijfbare mount is de bedoeling, én het risico. Het werk van de agent is jouw code veranderen, dus de projectdirectory is schrijfbaar, dus de sandbox kijkt rustig toe terwijl de agent iets schrijft dat jij later uitvoert, buiten de muur, met jouw rechten. Geen enkele isolatie beoordeelt een diff. De muur geeft je de zekerheid dat er verder niets is aangeraakt. Wat wél is aangeraakt, moet nog steeds langs jouw oordeel.
Nog één les uit het verhaal van Ona: nadat ze de handhaving naar de kernel hadden verplaatst, vond de agent een omweg via de ELF dynamic linker, die binaries laadt via een pad waar niemand aan gedacht had. Muren hebben kieren. Dat is een argument om lagen te stapelen, nooit om ze over te slaan. De inbraak waarbij niemand achter het stuur zat kwam precies zo ver als zijn grenzen toelieten, en die eigenschap haal je met een sandbox in huis.
Wat ik zelf draai
Mijn opzet, per vertrouwensniveau:
- Eigen repos, ik kijk mee:
/sandboxaan, netwerk-allowlist, plus de permission rules en hooks uit de permissions-gids. Lagen zijn goedkoop. - Runs zonder toezicht: een dev container met de default-deny firewall, het project als enige schrijfbare pad, en geen enkel geheim in de image. Dit is de enige plek waar
--dangerously-skip-permissionsmag bestaan. - Onvertrouwde code: een wegwerp-VM waar niets op staat dat het stelen waard is.
Het patroon achter alle drie is steeds hetzelfde. Bepaal vooraf wat de agent mag bereiken, dwing dat af buiten het proces, en laat de toestemmingsprompts weer worden wat ze altijd hadden moeten zijn: een zeldzame vraag die een echt antwoord verdient.
De agent hoeft niet kwaadaardig te zijn. Hij hoeft alleen plichtsgetrouw, geblokkeerd en vindingrijk te zijn, drie eigenschappen waar je hem op hebt uitgekozen. De muur is er voor de dag dat die drie een kant op wijzen die jij niet bedoelde.