Docker Sandbox Kit: Como isolar agentes de IA com segurança
Descubra como o Docker Sandbox Kit protege seu sistema contra riscos de agentes de IA autônomos e elimine as vulnerabilidades do docker.sock de vez.
Se você entrega o socket do Docker para um agente autônomo de programação, você está dando acesso root à sua máquina para um gerador probabilístico de texto.
Ferramentas como OpenHands, Aider e interfaces locais para o Claude Code quebram um galho enorme no dia a dia. O problema é que a documentação de quase todas sugere fazer o bind mount de /var/run/docker.sock para que o agente consiga criar imagens, rodar testes e gerenciar dependências de apoio. No segundo em que o modelo alucinar um comando, rodar código duvidoso de um repositório clonado ou cair em um prompt injection escondido em um arquivo README, esse acesso ao socket permite que ele escape do container e assuma o controle do seu sistema operacional.
A proposta da Docker de doar a especificação Sandbox Kit para a CNCF (Cloud Native Computing Foundation) mira diretamente nessa falha estrutural. Ao estender a camada de runtime da OCI (Open Container Initiative), a iniciativa busca padronizar ambientes de execução isolados com permissões granulares — aposentando o hábito arriscado de expor o daemon do host para fluxos autônomos.
Veja o que o Sandbox Kit da CNCF muda na prática, por que os métodos atuais de isolamento quebram e como proteger seus ambientes de agentes no Docker agora mesmo usando recursos nativos.
O atalho perigoso: por que o /var/run/docker.sock quebra a segurança
Agentes inteligentes precisam escrever código, instalar dependências, compilar binários e rodar testes de integração. Quando esses testes exigem um banco relacional ou uma instância de cache, o caminho mais rápido para quem desenvolve a ferramenta é repassar o socket do Docker do host para dentro do container do agente.
Esse atalho anula a principal barreira de segurança da máquina. No Linux, ter acesso a /var/run/docker.sock é o mesmo que ter privilégios de root irrestritos no sistema. O daemon do Docker roda como root. Qualquer processo que consiga trocar mensagens com esse socket UNIX pode disparar chamadas diretas de API para criar novos containers, montar qualquer pasta da máquina hospedeira e executar comandos com privilégios de kernel.
bash
O que um agente autônomo com acesso ao socket pode fazer com um único comando:
docker run --rm -v /:/host alpine rm -rf /host/etc
O agente nem precisa ter o binário do cliente docker instalado. Um script em Python ou um comando curl dentro do container conversa direto com o socket UNIX exposto:
# Escapando do container via chamada HTTP pura no socket do Docker
curl --unix-socket /var/run/docker.sock \
-H "Content-Type: application/json" \
-d '{"Image": "alpine", "Cmd": ["chroot", "/host", "useradd", "-m", "-G", "sudo", "backdoor"], "Binds": ["/:/host"]}' \
http://localhost/v1.43/containers/create
Existem três cenários críticos de falha quando você roda agentes com acesso ao daemon:
1. Escalada por Prompt Injection
Se o agente analisa um repositório Git de terceiros contendo uma mensagem de commit maliciosa, uma docstring adulterada ou uma issue envenenada, um prompt injection indireto pode instruir o modelo a tentar escapar do container. Com o socket montado, essa fuga é direta. A LLM assume que está apenas rodando uma rotina de testes para corrigir uma falha, mas na verdade está executando uma instrução que monta o disco do host em um container irmão.
2. Varredura de rede local privada (RFC 1918)
As redes do Docker operam por padrão em modo bridge com saída irrestrita. Um agente desgovernado ou manipulado consegue vasculhar as faixas de IP da sua rede interna (192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12). Ele pode alcançar compartilhamentos SMB abertos no seu NAS, interfaces web de roteadores e dashboards de homelab configurados sem autenticação mútua (mTLS). Se a sua rede local confia no tráfego interno, o agente transforma essa confiança em vetor de invasão.
3. Esgotamento de recursos da máquina host
Modelos de linguagem cometem erros com frequência. Loops infinitos, scripts de compilação sem travamento ou fork bombs acidentais vão devorar descritores de arquivos, memória RAM e ciclos de CPU se não houver limites estritos no nível do cgroups do kernel. Sem travas claras de processo e memória, um agente tentando rodar uma suite de testes pode congelar o host por completo.
O que a especificação Sandbox Kit da CNCF traz de novo
A especificação do Docker Sandbox Kit proposta à CNCF preenche o espaço vazio que existe entre máquinas virtuais tradicionais e containers simples.
Até então, quem precisava de execução segura para agentes ficava entre duas escolhas ruins: rodar máquinas virtuais aninhadas completas (como Firecracker ou QEMU), que consomem gigabytes de memória e demoram segundos para iniciar, ou apelar para o Docker-in-Docker (dind), que exige a perigosa flag --privileged e compartilha camadas demais com o host.
Padrão arriscado tradicional:
[ Container do Agente ] --(bind mount)--> [ /var/run/docker.sock ] --> Controle total do host
Padrão Sandbox CNCF:
[ Container do Agente ] --> [ OCI Sandbox Controller ] --> [ Execução efêmera ]
|- Nega acesso ao disco host |- Remove privilégios
|- Nega API do daemon |- Destrói ao encerrar
A especificação de sandbox da OCI detalha como os runtimes de container devem provisionar microambientes efêmeros sem dar acesso ao daemon de controle. Em vez de entregar a engine do Docker para o agente, o Sandbox Kit padroniza:
- Concessão granular de capacidades: Os agentes pedem ações operacionais pontuais (compilar código, disparar um processo filho, ouvir em uma porta local) em vez de receberem controle irrestrito do daemon.
- Ciclos de vida declarativos e efêmeros: Os ambientes sobem sob demanda para comandos isolados ou baterias de testes curtas e somem na sequência, sem deixar resíduos nos volumes ou no storage driver da máquina.
- Flexibilidade de runtime: Pouco importa se o backend roda em cima de namespaces de usuário do Linux ou hypervisors leves para microVMs (como gVisor ou Kata Containers); o agente conversa sempre com uma interface única de baixo privilégio.
- Planos de controle isolados: O daemon de orquestração fica isolado atrás de uma camada de autorização. O agente não enxerga outros containers ativos, placas de rede locais ou pools de armazenamento do sistema.
Comparativo de estratégias de isolamento
Enquanto a especificação do Sandbox Kit ainda avança na CNCF, quem mantém servidores ou homelabs precisa escolher uma abordagem baseada no risco aceitável e no hardware disponível.
| Estratégia | Risco de Exposição do Host | RAM Base por Agente | Tempo de Inicialização | Complexidade |
|---|---|---|---|---|
Montar docker.sock |
Crítico (Root completo no host) | ~50 MB | Instantâneo | Trivial |
Docker-in-Docker (dind) |
Alto (Exige --privileged) |
~400 MB | 3 a 8 segundos | Moderada |
| Podman / Docker Rootless | Baixo (Barreira de namespaces do kernel) | ~100 MB | 1 a 2 segundos | Moderada |
| Compose Endurecido (Recomendado) | Muito Baixo (Perfil OCI restrito) | ~128 MB | Instantâneo | Baixa |
| CNCF Sandbox Kit (Em breve) | Mínimo (API granular de permissões) | Dinâmica | Sub-segundo | Nativa |
Avaliando os prós e contras
- Montar
docker.sock: Não consome recursos adicionais, mas a segurança é inexistente. Nunca rode código autônomo gerado por LLMs com essa configuração. - Docker-in-Docker (
dind): Cria um daemon secundário dentro do container e isola o daemon principal. Só que fazer o driver de storage overlay e o cgroups funcionarem internamente costuma exigir o parâmetro--privileged, que desativa filtros seccomp, AppArmor e as travas de capacidades do kernel. - Podman / Docker Rootless: Usa namespaces de usuário (
userns) para que orootdo container seja mapeado para um usuário sem privilégios no sistema real. Evita que o host seja comprometido, mas exige configurações manuais desubuid/subgide permissões de volume. - Compose Endurecido: Usa recursos que já estão instalados no seu Docker. Ao derrubar todas as capacidades do Linux, travar o sistema de arquivos como somente leitura, limitar uso de RAM/CPU e isolar a rede, você garante defesa em profundidade eficiente sem precisar mexer em hypervisors complexos.
Como isolar agentes de IA no Docker hoje mesmo
Não é preciso esperar os padrões upstream chegarem nas distribuições Linux estáveis para ter segurança. Você consegue um isolamento forte hoje configurando um arquivo de Docker Compose com as diretivas certas.
O exemplo a seguir aproveita os mecanismos nativos do Kernel Linux 5.15+: cgroups v2, seccomp, descarte de capabilities e uma rede bridge interna sem rota para a sua rede local.
Salve a configuração abaixo como compose.agent-sandbox.yaml:
services:
agent-runner:
image: python:3.11-slim
container_name: agent_sandbox
restart: "no"
# Executa com usuário comum sem privilégios (UID 1000)
user: "1000:1000"
# Bloqueia escalada de privilégios (ignora binários setuid como sudo/su)
security_opt:
- no-new-privileges:true
# Remove todas as permissões especiais do kernel Linux
cap_drop:
- ALL
# Trava o sistema de arquivos base do container em modo somente leitura
read_only: true
# Cria diretórios temporários descartáveis alocados apenas na RAM do host
# As flags noexec, nosuid e nodev impedem a execução de binários nessas pastas
tmpfs:
- /tmp:size=1G,noexec,nosuid,nodev,uid=1000,gid=1000
- /run:size=64M,noexec,nosuid,nodev,uid=1000,gid=1000
# Evita fork bombs e limita o uso de hardware do host
pids_limit: 100
deploy:
resources:
limits:
cpus: "2.0"
memory: 2048M
reservations:
memory: 128M
# Redireciona caches de pacotes para a memória RAM (tmpfs) para viabilizar o modo read_only
environment:
- HOME=/workspace
- TMPDIR=/tmp
- PIP_CACHE_DIR=/tmp/.cache/pip
- npm_config_cache=/tmp/.npm
# Monta apenas a pasta de trabalho do projeto
volumes:
- type: bind
source: ./workspace
target: /workspace
read_only: false
working_dir: /workspace
# Rede fechada: corta rotas de saída e bloqueia acesso à sua rede interna
networks:
agent_sandbox_net:
aliases:
- sandbox
networks:
agent_sandbox_net:
driver: bridge
internal: true # Bloqueia roteamento externo e varredura da LAN
Por que essa configuração funciona
cap_drop: [ ALL ]: Remove todas as permissões de superusuário do kernel. Se o código do agente encontrar uma falha local, ele não terá permissão para alterar rotas de rede, mexer no relógio do sistema, subir módulos de kernel ou inspecionar outros processos viaptrace.security_opt: [ "no-new-privileges:true" ]: Impede que qualquer subprocesso obtenha privilégios adicionais por meio de binários com bitssetuidousetgid. Se alguém injetar um executável malicioso com flag de suid dentro de/workspace, ele não surtirá efeito.read_only: true: Congela a raiz do container. O agente não consegue instalar backdoors persistentes nas pastas do sistema operacional, alterar o/etc/resolv.confou corromper binários nativos do container.tmpfs: Ferramentas comopipenpmprecisam descompactar arquivos e gerar arquivos de lock temporários. Ao montar umtmpfsem/tmp, o agente ganha uma área de trabalho temporária restrita à RAM, limitada a 1 GB e limpa na hora em que o container para.pids_limit: 100: Coloca um limite rígido na quantidade de processos simultâneos. Se a LLM alucinar e gerar um loop recursivo descontrolado ou uma fork bomb, o kernel encerra as threads excedentes em vez de travar a máquina hospedeira.internal: true: Essa diretiva isola a interface de rede bridge. O container fica completamente impedido de falar com roteadores, outros dispositivos na sua rede interna ou servidores na internet.
Testando o isolamento do agente
Para validar o ambiente de sandbox, crie uma pasta local para a área de trabalho e inicie o container:
# Cria o diretório de trabalho com permissão para o UID 1000
mkdir -p workspace
chown -R 1000:1000 workspace
# Executa um comando de teste dentro da sandbox
docker compose -f compose.agent-sandbox.yaml run --rm agent-runner python3 -c "
import os
print(f'User UID: {os.getuid()}')
print(f'Filesystem writable: {os.access(\"/etc\", os.W_OK)}')
print(f'Workspace writable: {os.access(\"/workspace\", os.W_OK)}')
"
A saída precisa confirmar que o processo roda com UID 1000, que a pasta /etc está bloqueada para escrita e que apenas /workspace aceita alterações:
User UID: 1000
Filesystem writable: False
Workspace writable: True
Problemas comuns ao isolar agentes (e como contornar)
Fique atento a estes problemas práticos antes de subir agentes em containers restritos:
1. Falha com gerenciadores de pacotes em modo somente leitura
Definir read_only: true quebra comandos como npm install, pip install ou cargo build logo de cara, porque esses utilitários tentam gravar diretórios de cache em /root/.cache, /home/node ou /workspace/.cache.
Ajuste isso apontando as variáveis de ambiente dos diretórios de cache para a pasta temporária em /tmp:
environment:
- PIP_CACHE_DIR=/tmp/.cache/pip
- npm_config_cache=/tmp/.npm
- CARGO_HOME=/tmp/.cargo
- GOCACHE=/tmp/.go-cache
Caso os scripts de build precisem rodar binários gerados durante o processo dentro de /tmp, remova o parâmetro noexec da linha do /tmp no Compose:
tmpfs:
- /tmp:size=1G,nosuid,nodev,uid=1000,gid=1000
2. Achar que redes bridge padrão do Docker são isoladas
Por padrão, uma rede comum de container alcança o endereço de IP do host e qualquer equipamento na sua rede local física (endereços RFC 1918). Se você esquecer o parâmetro internal: true, o container conseguirá se comunicar com seu roteador, outros containers de homelab e servidores internos. Use sempre internal: true ou defina regras estritas via nftables/iptables na interface da bridge.
Se o seu fluxo de desenvolvimento realmente precisa de internet para puxar bibliotecas externas, passe o tráfego por um forward proxy explícito (como Squid ou Tinyproxy) configurado com uma lista de domínios permitidos restrita aos repositórios oficiais (pypi.org, npmjs.org):
[ Agente protegido ] ---> [ Forward Proxy (Lista permitida) ] ---> [ PyPI / npm ]
|
x (Bloqueado: 192.168.1.0/24 e 10.0.0.0/8)
3. Habilitar capacidades cegas para debuggers
Quando agentes tentam utilizar utilitários como o gdb ou profiladores de memória, eles costumam pedir a permissão SYS_PTRACE. Conceder SYS_PTRACE enfraquece o isolamento de processos dentro de namespaces compartilhados. Se a sua rotina exige inspeção profunda de chamadas de sistema, rode o agente em uma microVM de verdade (como Firecracker) em vez de enfraquecer seus perfis seccomp no Docker.
4. Conflitos de permissão de arquivo e mapeamento de UID/GID
Se os arquivos do seu projeto no host pertencem ao UID 501 (padrão no macOS) ou UID 1000 (comum no Linux monousuário), mas o container roda com um usuário diferente, o agente vai falhar com erros de "permission denied" sempre que tentar salvar um arquivo editado. Garanta que a diretiva user: no Compose bata com o seu usuário local:
# Descubra seu UID e GID atuais
id -u
id -g
# Passe os identificadores na inicialização do container
UID_GID="$(id -u):$(id -g)" docker compose -f compose.agent-sandbox.yaml run --user "$UID_GID" --rm agent-runner bash
Perguntas frequentes (FAQ)
O que é a especificação Sandbox Kit doada à CNCF?
É uma especificação aberta pensada para padronizar como engines de containers constroem, operam e isolam ambientes descartáveis de execução. Ela entrega para agentes de IA e ferramentas de automação uma interface comum e de menor privilégio, eliminando a dependência do socket do daemon Docker do host.
Como executar código de LLM e agentes com segurança no Docker?
Rode o container sem nenhum bind mount de /var/run/docker.sock. Configure um usuário comum sem privilégios de root, descarte todas as capacidades do kernel usando cap_drop: [ALL], trave o sistema de arquivos como somente leitura (read_only: true), isole o container em uma rede bridge com internal: true e defina limites restritos de memória, CPU e contagem de processos via cgroups v2.
Por que montar o /var/run/docker.sock em agentes inteligentes é perigoso?
O socket do Docker é uma API de controle direto e irrestrito para o daemon no host, que executa como root. Qualquer processo que envie comandos para ele tem o mesmo poder do administrador da máquina. Um agente que receba instruções maliciosas por prompt injection pode usar essa porta para montar o disco rígido do host dentro de outro container, ler arquivos protegidos ou criar contas com acesso permanente ao sistema.
Qual a diferença entre o Sandbox Kit da CNCF e o Docker-in-Docker (dind)?
O Docker-in-Docker tradicional depende de containers filhos rodando com o argumento --privileged e permissões amplas de kernel, abrindo brechas consideráveis na máquina física. O Sandbox Kit da CNCF trabalha direto na camada da OCI para instanciar microambientes enxutos e isolados, impondo limites operacionais sem precisar de daemons privilegiados rodando dentro de outros containers.
Leia também no cluster
- /en/posts/cursor-xai-vs-local-llms-privacy-guide-for-homelabs/
- /en/posts/docker-sandbox-kit-spec-v3-hardening-ai-agent-containers/
- /en/posts/docker-sandboxes-secure-isolation-for-autonomous-ai-agents/
Aplique as regras de isolamento no seu Compose antes de dar permissão para qualquer script de LLM rodar localmente. Teste primeiro a escrita nas pastas permitidas, confira se o acesso à rede interna está bloqueado e monitore o comportamento dos processos. É bem mais tranquilo perder dez minutos ajustando permissões do que passar a tarde restaurando arquivos do sistema operacional.
Relacionados neste cluster
- /pt/posts/como-isolar-agentes-ia-docker-sandbox/
- /pt/posts/como-isolar-agentes-ia-docker/
- /pt/posts/como-isolar-containers-docker-seguranca/
Espaço publicitário · não é endosso do Umbrel