Context
Naar aanleiding van een rondgaande post over een Copilot CLI die in een Docker-container tóch host-root kreeg (user in de docker group + gemounte Docker-socket = root-equivalent), is de huidige sandbox tegen het licht gehouden.
Goed nieuws: die specifieke aanvalsketen geldt niet voor onze sandbox:
- Geen Docker-socket gemount (
compose.yml mount alleen claude-home + projects).
- Geen
docker CLI / docker group in de container; geen DinD; geen --privileged.
- User
claude is non-root, sudo beperkt tot precies één script (init-firewall.sh).
- Enige caps:
NET_ADMIN/NET_RAW (firewall).
Het reële aandachtspunt: de Maven host-agent
claude-sandbox/host-agents/maven/maven_agent.py is per ontwerp een container→host code-execution-bridge: een MCP-server die mvn draait namens Claude in de container. Dit is bewust (rootless Docker in de container kan geen sibling-containers starten voor Testcontainers).
Directe OS-command-injectie via de tool-args is afgevangen (subprocess.run met list-vorm, geen shell=True, vaste argv[0]). Maar willekeurige host-code via Maven is triviaal:
- Maven-goals zelf — bv.
exec-maven-plugin:exec met -Dexec.executable=/bin/sh.
- pom.xml — de
projects-map is een gedeeld bind-mount; Claude controleert de pom.xml die de host uitvoert. Een plugin gebonden aan de validate-phase draait bij élke goal.
- mvnw-wrapper — ligt PROJECT_DIR in de gedeelde map, dan kan Claude
mvnw schrijven/overschrijven; de agent voert dat direct uit als host-user (niet eens "via maven").
Daarnaast: op Linux bindt de agent op 0.0.0.0:7777 zonder authenticatie (run.sh waarschuwt hier al voor) → ook het netwerk kan dit misbruiken.
Gevolg: wat Claude in de sandbox kan, kan het via deze bridge uitvoeren als de host-user die run.sh startte. Draait die user in de docker group of heeft die sudo, dan is host-escalatie alsnog mogelijk — niet via de container, maar via de host-user.
Voorstel: opties afwegen + documenteren
Goedkope hardening (past bij het realistische dreigingsbeeld — Claude rogue / prompt-injection)
Sterkere isolatie (alleen als runner echt onvertrouwde code draait)
⚠️ Niet doen: runner-container mét gemounte Docker-socket (om Testcontainers te laten werken). Dat reproduceert exact de Copilot-bug (socket = host-root).
Afweging op threat model
| Adversary |
Maatregel |
| Claude rogue / prompt-injection (semi-vertrouwd) |
Goedkope hardening — ~90% winst, lage kosten |
| Onvertrouwde code, Linux-host |
Optie C (sysbox) |
| Volledig vijandige code, multi-tenant/CI, kernel-escape in scope |
Optie D (microVM) |
Platform-nuance
run.sh draait native op het echte OS (ook op Mac/Windows — niet in de Docker-VM). C en D gaan uit van een Linux-host met moderne kernel / KVM; voor Mac/Windows-gebruikers niet zomaar inzetbaar. Mee te wegen.
Definition of done
Context
Naar aanleiding van een rondgaande post over een Copilot CLI die in een Docker-container tóch host-root kreeg (user in de
dockergroup + gemounte Docker-socket = root-equivalent), is de huidige sandbox tegen het licht gehouden.Goed nieuws: die specifieke aanvalsketen geldt niet voor onze sandbox:
compose.ymlmount alleenclaude-home+projects).dockerCLI /dockergroup in de container; geen DinD; geen--privileged.claudeis non-root, sudo beperkt tot precies één script (init-firewall.sh).NET_ADMIN/NET_RAW(firewall).Het reële aandachtspunt: de Maven host-agent
claude-sandbox/host-agents/maven/maven_agent.pyis per ontwerp een container→host code-execution-bridge: een MCP-server diemvndraait namens Claude in de container. Dit is bewust (rootless Docker in de container kan geen sibling-containers starten voor Testcontainers).Directe OS-command-injectie via de tool-args is afgevangen (
subprocess.runmet list-vorm, geenshell=True, vasteargv[0]). Maar willekeurige host-code via Maven is triviaal:exec-maven-plugin:execmet-Dexec.executable=/bin/sh.projects-map is een gedeeld bind-mount; Claude controleert depom.xmldie de host uitvoert. Een plugin gebonden aan devalidate-phase draait bij élke goal.mvnwschrijven/overschrijven; de agent voert dat direct uit als host-user (niet eens "via maven").Daarnaast: op Linux bindt de agent op
0.0.0.0:7777zonder authenticatie (run.sh waarschuwt hier al voor) → ook het netwerk kan dit misbruiken.Gevolg: wat Claude in de sandbox kan, kan het via deze bridge uitvoeren als de host-user die
run.shstartte. Draait die user in dedockergroup of heeft die sudo, dan is host-escalatie alsnog mogelijk — niet via de container, maar via de host-user.Voorstel: opties afwegen + documenteren
Goedkope hardening (past bij het realistische dreigingsbeeld — Claude rogue / prompt-injection)
run.shals dedicated least-privilege host-user (niet indockergroup, geen sudo) — documenteren indocs/maven-mcp-agent.md.projects-map (Claude kan dan geen pom.xml/mvnw schrijven die de host draait).127.0.0.1of firewall poort 7777; waarschuwing aanscherpen.Sterkere isolatie (alleen als runner echt onvertrouwde code draait)
dockerd, raakt host-daemon niet). Testcontainers werkt, host-escalatie dicht. Praktisch Linux-only, recente kernel.Afweging op threat model
Platform-nuance
run.shdraait native op het echte OS (ook op Mac/Windows — niet in de Docker-VM). C en D gaan uit van een Linux-host met moderne kernel / KVM; voor Mac/Windows-gebruikers niet zomaar inzetbaar. Mee te wegen.Definition of done
SECURITY.md-sectie.docs/maven-mcp-agent.md.