Context
2026-06-12 tower security audit flagged xiaozhi-esp32-server as the biggest container-escape vector on the host: it binds /var/run/docker.sock + /usr/bin/docker (docker-compose.yml.template ~L60-66, warning comment already present) while listening on 0.0.0.0:8000/8003. Any RCE in the voice websocket/HTTP surface = effective root on the Unraid host.
Sole consumer
custom-providers/pi_voice/pi_client.py — spawns docker exec -i dotty-pi pi --mode rpc ... (local path, pi_client.py:90; ssh variant :72). Nothing else in the repo or live appdata uses the socket (dances.py / xiaozhi-patches grep clean).
Options
- Preferred — remove the exec hop entirely. Have
dotty-pi own the pi --mode rpc process and expose it on the compose network (tiny TCP/unix-socket shim, stdin/stdout framing unchanged). pi_client.py gains a connect spawn-strategy alongside the existing local/ssh ones. Then delete the socket + CLI mounts from the template. Voice container ends up with zero host privileges.
- Interim —
tecnativa/docker-socket-proxy with only CONTAINERS=1 + exec POST endpoints allowed. Low value: exec into arbitrary containers is still near-root; only blocks docker run --privileged.
- Do nothing — risk is documented in the template, but post-audit the rest of the host is now hardened (key-only SSH, no guest SMB writes, delugevpn unprivileged), leaving this as the standout gap.
Acceptance
docker inspect xiaozhi-esp32-server shows no /var/run/docker.sock or /usr/bin/docker mounts
- PiVoiceLLM voice round-trip still works (Dotty answers via pi RPC)
- compose.all-in-one.yml comment block updated to match
🤖 Generated with Claude Code
Context
2026-06-12 tower security audit flagged
xiaozhi-esp32-serveras the biggest container-escape vector on the host: it binds/var/run/docker.sock+/usr/bin/docker(docker-compose.yml.template ~L60-66, warning comment already present) while listening on0.0.0.0:8000/8003. Any RCE in the voice websocket/HTTP surface = effective root on the Unraid host.Sole consumer
custom-providers/pi_voice/pi_client.py— spawnsdocker exec -i dotty-pi pi --mode rpc ...(local path,pi_client.py:90; ssh variant:72). Nothing else in the repo or live appdata uses the socket (dances.py / xiaozhi-patches grep clean).Options
dotty-piown thepi --mode rpcprocess and expose it on the compose network (tiny TCP/unix-socket shim, stdin/stdout framing unchanged).pi_client.pygains aconnectspawn-strategy alongside the existing local/ssh ones. Then delete the socket + CLI mounts from the template. Voice container ends up with zero host privileges.tecnativa/docker-socket-proxywith onlyCONTAINERS=1+ exec POST endpoints allowed. Low value: exec into arbitrary containers is still near-root; only blocksdocker run --privileged.Acceptance
docker inspect xiaozhi-esp32-servershows no/var/run/docker.sockor/usr/bin/dockermounts🤖 Generated with Claude Code