Sin docker.sock en el agente: el bot no es root del host
Resumen
Cómo no entregar el daemon a un webhook: no montes /var/run/docker.sock en Compose. Distinto de usuario no-root. Docker Engine attack surface, 3 de septiembre de 2026. Quien tiene el socket es root efectivo del VPS.

Qué resuelve
Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.
Montar /var/run/docker.sock en el agente es root del host. Un prompt injection o un tool run y alguien hace docker run -v /:/host. Distinto de USER 1000: uid 1000 + socket = daemon API. Fuentes oficiales consultadas el 3 de septiembre de 2026.
La regla
No hay volumes: ["/var/run/docker.sock:/var/run/docker.sock"] en el servicio agent. Ni en Caddy. Ni “solo lectura”: el API sigue ahí.
Si necesitas orquestar, un job de CI en el host o un servicio profile ops que no reciba webhooks.
Attack surface oficial
Docker documenta el socket como superficie del daemon. TLS de daemon, rootless, user namespaces: otro nivel. El default VPS + sock en el bot es el peor.
cap_drop y no-new-privileges no tapan el socket.
Tabla

| Quién | sock | Por qué |
|---|---|---|
| agent webhook | no | untrusted input |
| CI runner | a veces | pipeline, no prod 24/7 |
| Watchtower | no | pull_policy |
| Portainer 24/7 | no junto al bot | superficie extra |
Errores comunes

| Síntoma | Causa | Fix |
|---|---|---|
| “docker from inside” | sock | quítalo |
tool docker ps | SDK | no |
| :ro en sock | mito | API igual |
| group docker | gid 999 | no |
| DinD | nested | no en el webhook |
Relación con el resto
- USER: no-root.
- Caps: cap_drop.
- Secrets: compose secrets.
- Ports: expose vs ports.
Checklist
-
compose configsin docker.sock -
compose exec agent ls /var/run/docker.sockENOENT - no SDK docker en el bot
- deploy = CI, no el agente
- Ensayo: grep sock en yaml
- rootless daemon aparte si insistes
FAQ
¿Workers? No hay sock.
¿Fly? Machines API con token, no sock local.
¿Testcontainers en CI? CI, no prod.
El ensayo: grep el repo. Cero mounts. Un test de integración no justifica prod.
El agente llama APIs HTTP. Docker lo opera un humano o Actions.
Qué no hacer
No uses el agente como “mini PaaS” que docker run tools. Eso es un orquestador con RCE. Un worker con imagen fija y shm si hay browser.
No montes docker.sock :ro y un proxy TCP al daemon “más seguro” en el mismo compose que el webhook. Sigue siendo control del host.
privileged: true + sock = no hay discusión. no-new-privileges no aplica al API del daemon.
Techos oficiales
Engine security: whoever talks to the daemon can start containers, bind mounts, steal secrets. Compose volumes bind es el vector. No hay flag “sock pero inocente”.
Rootless Docker reduce el blast al user; el webhook sigue sin necesitarlo.
CI vs runtime
GitHub Actions monta sock en runners hosted a veces. No copies ese yaml al VPS. cicd construye; prod solo corre el binario.
El ensayo extra: grep -R docker.sock compose*.yml vacío. docker inspect agent sin binds a /var/run.
kill-switch no sirve si el atacante ya tiene el daemon: recrea el bot. Quita el sock primero.
Un sidecar “docker proxy” con allowlist sigue siendo privilegio. YAGNI. El webhook no orquesta contenedores.
Siguiente paso: si el sock ya no está y el yaml pide docker CLI, sácalo del image runner (multistage). Sin runtime: curso.
Lecturas relacionadas
Sigue explorando Deploy y otras piezas para builders.



