Rootless nunca foi isento de riscos: um playbook para CTOs após o CopyFail (CVE-2026-31431)

Por Diogo Hudson Dias
An SRE in an operations room working on a laptop in front of illuminated server racks, applying urgent kernel patches.

Se você precisou aplicar patches de emergência em nós Linux na semana passada, já recebeu o recado: rootless não significa inofensivo. CopyFail (CVE-2026-31431) abriu um novo buraco pelos user namespaces e lembrou todo mundo de que o kernel é a verdadeira superfície de ataque. Contêineres rootless reduzem o raio de explosão; eles não removem o risco no kernel. Se suas equipes deixam código não confiável rodar em contêineres rootless, você estava apostando seu cluster em uma mistura de esperança e uma tabela de syscalls.

O que mudou com o CopyFail (e por que era previsível)

O governo dos EUA emitiu um alerta severo sobre o CopyFail afetando versões principais do Linux, e as equipes de segurança correram. As primeiras análises mostraram como um bug em um caminho central do kernel poderia permitir escape de contêiner — mesmo em ambientes “rootless” que muitos de nós usávamos como um cobertor de segurança para máquinas de desenvolvedores, sandboxes de CI ou recursos SaaS multi-tenant.

Isso não é um evento isolado. Já estivemos aqui: Dirty COW (CVE-2016-5195), Dirty Pipe (CVE-2022-0847), o breakout do runc (CVE-2019-5736) e um fluxo constante de peculiaridades de user namespaces e overlayfs. A lição principal é a mesma toda vez: se o kernel faz parte da sua fronteira de confiança, você eventualmente vai perder para um bug no kernel. Rootless ajuda, mas não é um sandbox. É um conjunto diferente de armas apontadas para o próprio pé.

Em paralelo, atacantes estão explorando em massa outros pontos fracos (vide a onda de bugs no cPanel). Quando há um caminho amplamente “armável” para obter root ou escapar, a internet vira seu red team. Assuma uma janela de 24–72 horas do PoC até a varredura em larga escala. Se seu processo de patch é mais lento do que isso, você não tem um problema de vulnerabilidade — você tem um problema de operações.

Para CTOs: transforme isso em uma decisão clara de isolamento

Seu trabalho não é virar especialista em kernel. Seu trabalho é definir uma política: quais workloads recebem qual isolamento, com que velocidade você aplica patches e o que você faz quando o sandbox falha. Aqui vai um framework concreto que usamos com clientes.

1) Classifique workloads por confiança e raio de impacto

  • Tier 0 (Serviços internos confiáveis): Seu próprio app e infraestrutura, single-tenant, sem código ou binários fornecidos por clientes.
  • Tier 1 (Caminhos de código estendidos por parceiros): Plugins, filtros WASM, transformações de dados construídas por parceiros confiáveis com contratos e auditorias.
  • Tier 2 (Lógica/dados fornecidos por clientes com execução): Funções de clientes, geradores de relatórios, UDFs em SQL, adaptadores de modelos, builds de preview de PR.
  • Tier 3 (Hostil à internet/não confiável): Envios públicos, CI para repositórios externos, sandboxes efêmeros, agentes executando ferramentas arbitrárias, qualquer coisa que faça parsing e/ou execução de entrada de usuário em escala.

O limite de decisão é simples: se um bug no kernel ou no runtime puder permitir que um workload Tier 2/3 alcance o host ou outro tenant, mova-o agora para um sandbox mais forte.

2) Escolha o isolamento que combina com o tier

  • Contêineres simples (rootful ou rootless) em um kernel compartilhado: Aceitável para Tier 0 se você aplicar hardening (seccomp, AppArmor/SELinux, root somente leitura, sem escalonamento de privilégios). Use rootless especificamente para developer laptops e CI leve, mas trate-o como conveniência, não como fronteira de segurança.
  • gVisor (runsc) / GKE Sandbox / Azure Kata-WSL2 equivalente: Um sandbox de compatibilidade de syscalls que interpõe na API do kernel. Bom para Tier 1–2. Overhead típico: 10–30% em workloads intensivas em syscalls, quase nativo em CPU-bound, penalidade pequena de latência p99 (+0,5–2 ms) para microsserviços intensivos em rede. Números variam; meça no seu código.
  • Kata Containers com microVMs Firecracker/KVM: Virtualização por hardware com microVMs por pod. Bom para Tier 2–3. CPU quase nativa (3–10% de overhead), “imposto” de memória ~50–120 MB por sandbox, cold starts +150–400 ms. Forte isolamento entre tenants com custo moderadamente previsível.
  • VMs completas ou FaaS gerenciadas com sandboxes reforçados: Para o verdadeiramente hostil. Se você executa código público, análise de malware ou marketplaces de agentes, isso é o padrão. Mais pesado em operações a menos que use um serviço gerenciado.

Pé no chão: se um workload é Tier 2 ou 3 e você ainda está em contêineres rootless porque “é mais simples”, você está aceitando um raio de impacto de um kernel-day que o CopyFail acabou de tornar bem tangível.

3) Orce o overhead de forma realista

Isolamento não é de graça. Planeje:

  • CPU: Kata/Firecracker adiciona ~3–10% em microsserviços típicos; gVisor 10–30% em caminhos intensivos em syscalls. Para inferência ou compressão CPU-bound, o overhead pode ficar abaixo de 5%.
  • Memória: MicroVMs custam ~50–120 MB/pod a mais que contêineres simples. 100 desses pods ≈ 5–12 GB de RAM extra no pool de nós. Em nós limitados por memória, isso é o fator limitante.
  • Latência: gVisor costuma adicionar até ~2 ms no p99; cold starts do Kata adicionam 150–400 ms por pod, a menos que você faça pool ou pré-aqueça sandboxes. Serviços de longa duração amortizam isso; tráfego com picos demanda pools aquecidos.

Traduza isso em dólares. Se seu cluster gasta US$ 80k/mês em compute, mover 20% dos pods para Kata pode adicionar 5–8% de custo (US$ 4–6k/mês). Isso é mais barato do que um único incidente de segurança com comprometimento de host e notificações a clientes.

Seu plano de hardening em 6 partes para 2026

1) Estratégia de kernel e SO

  • Fixe-se em kernels LTS com backports do fornecedor (Ubuntu LTS HWE, RHEL, Bottlerocket). Evite rodar duas “linhas” de kernel diferentes no mesmo cluster — diversidade complica patches de emergência.
  • Runbook de “exploit como Sev-1”: Trate um CVE crítico de escape de contêiner como um Sev-1. Faça drain automático e patch em até 24 horas. Mire 6 horas para bugs exploráveis pela internet. Pratique duas vezes por ano.
  • Evite combinações exóticas de filesystem e namespaces a menos que testadas sob carga (idmapped mounts, recursos de borda do overlayfs). Eles ampliam sua superfície de ataque no kernel.

2) Controles de runtime que realmente fazem diferença

  • Perfis seccomp padrão: Bloqueie syscalls perigosas para tudo. Docker e containerd já trazem defaults sensatos; personalize por serviço. Se um time pedir syscalls sem limites, trate como exceção com aprovação formal.
  • SELinux/AppArmor em enforcing: Escolha um e mantenha ligado. LSM desativado é um canário de cultura relaxada.
  • No-new-privileges, root somente leitura, remoção de capabilities por padrão: Negue CAP_SYS_ADMIN, CAP_NET_RAW, CAP_SYS_MODULE em todo lugar, a menos que exista um ticket e uma exceção com prazo.
  • Protegendo o “rootless” direito: Use userns remap, restrinja mounts do host e trate rootless como uma camada de conforto para máquinas de dev — não uma dispensa de política para workloads não confiáveis.

3) Políticas de Kubernetes que mandam os pods certos para os sandboxes certos

  • RuntimeClass: Defina classes como native, gvisor, kata. O admission control (Kyverno/Gatekeeper) deve impor que namespaces Tier 2–3 só implantem em kata ou gvisor.
  • Segurança de pods: Faça cumprir as políticas baseline ou restricted em todo o cluster. Default‑deny para hostNetwork, hostPID, hostIPC e privileged. Exija readOnlyRootFilesystem: true.
  • Pools de nós e taints: Separe pools de nós para runtimes com sandbox. Aplique taints para que apenas pods que solicitam a RuntimeClass correspondente agendem ali.
  • Opções gerenciadas primeiro: GKE Sandbox (gVisor) é plug and play. AKS suporta Kata via Confidential Containers. EKS suporta Kata com containerd e Bottlerocket. Use o que a nuvem já oferece, a menos que você precise de controle sob medida.

4) Decisões na supply chain que reduzem o raio de impacto

  • Imagens distroless/minimais: Menos binários, menos subsistemas, menos surpresas. Faça scan por arquivos setuid; bloqueie-os.
  • Assine e verifique: Use Sigstore/cosign e imponha verificação na admissão. Mantenha SBOMs e alerte sobre desvio.
  • Imagens base imutáveis: Cadência mensal de refresh com backports de segurança. Se uma imagem tiver mais de 60 dias, recuse a implantação sem exceção.

5) Observabilidade que detecta comportamentos “impossíveis”

  • Detecção de anomalias de syscalls: Falco ou sensores eBPF podem flagrar pivôs de contêiner para host. Não confie nisso como escudo; use para reduzir o tempo até saber.
  • Sinais dourados por runtime: Acompanhe cold starts, RSS por sandbox e deltas de p99 vs baseline. Se Kata adiciona 300 ms em um caminho com SLO de 200 ms, isso é problema de design, não de segurança.
  • Canários de exploit: Mantenha um pod de teste que tenta comportamentos de escape conhecidos em não‑produção. Alerta se algo atípico tiver sucesso após um ciclo de patch.

6) Pessoas e processo: velocidade é seu fosso

  • Defina um SLO de patch: CVEs críticos de escape de contêiner patchados em até 24 horas. Audite isso como uptime.
  • Processo de exceção com kill switch: Se um time precisar de hostNetwork ou capabilities extras, faça a exceção expirar em 14 dias e notifique segurança na renovação.
  • Habilitação de times nearshore: Dê aos engenheiros remotos sandboxes self‑service com a RuntimeClass correta embutida. Não deixe a conveniência empurrá-los de volta para “é só rodar o docker com --privileged”.

Onde rootless ainda faz sentido

Não jogue o rootless fora. Ele ainda traz segurança no mundo real em máquinas de dev e alguns runners de CI:

  • Notebooks de desenvolvedores: Rootless + remapeamento de user namespaces significa menos modificações acidentais no host e padrões de mount menos arriscados. Combine com uma VM de dev dedicada e você reduz ainda mais o raio de impacto.
  • CI básico para o seu próprio código: Rootless é ok para construir e testar seus serviços com bases imutáveis e sem compiladores ou interpretadores de terceiros puxando da internet durante o build. No momento em que você aceitar PRs não confiáveis ou toolchains arbitrárias, migre para Kata ou gVisor.

O modelo mental: rootless é um formão afiado em madeira conhecida. MicroVMs são as luvas de segurança quando você entrega o formão a um desconhecido.

Como implantar isso sem reescrever tudo

Semanas 0–2: decida e comprove

  • Marque 10 serviços como Tier 2 ou 3. Escolha dois para migrar primeiro — um sensível a latência e um intensivo em CPU.
  • Crie um pool de sandboxes: Um node group com Kata e um com gVisor (gerenciado onde possível). Defina objetos RuntimeClass e aplique taints nos nós.
  • Meça antes/depois: Faça baseline de latência p50/p99, CPU, RSS, cold start e taxas de erro para esses dois serviços. Aceite que +5–10% é o custo de fazer negócios com código hostil.

Semanas 3–6: faça a política valer

  • Admission control ligado: Regras em Gatekeeper/Kyverno que forçam namespaces Tier 2/3 a usar kata ou gvisor; bloqueie flags privilegiadas; exija readOnlyRootFilesystem.
  • Guardrails da supply chain: Verificação com Cosign obrigatória; imagens com mais de 60 dias rejeitadas; nenhum arquivo setuid permitido nas imagens.
  • SLO de patch valendo: Pratique o runbook de drain-and-patch. Acompanhe o tempo médio até o patch e publique isso como uptime.

Semanas 7–12: otimize e expanda

  • Dimensione corretamente os pools: Memória é o limitador com Kata. Se cada sandbox custa +80 MB e você agenda 300 pods por node group, isso dá +24 GB. Escalone nós de acordo ou reduza a densidade de pods.
  • Pré-aqueça sandboxes: Para sistemas com picos, mantenha um pool de VMs Kata aquecidas ou troque esses caminhos para gVisor se latência for o mais importante.
  • Amplie a cobertura: Migre o restante do Tier 2 e quaisquer serviços Tier 1 que façam parsing de formatos complexos controlados por atacantes (PDFs, arquivos, imagens, weights de modelos).

O que não fazer

  • Não confie em “privileged but careful”. Contêineres privilegiados são um shell no host com marketing. Se você precisa disso, isole em um pool de nós dedicado atrás de um jump host e trate como pet.
  • Não assuma que o monitoramento vai salvá-lo. Detecção reduz o raio de impacto após o comprometimento; não o previne. Bugs na classe CopyFail exigem prevenção e patch rápido.
  • Não confunda conveniência de dev com política de produção. Rootless é ótimo localmente. Isso não o torna uma estratégia multi-tenant.

Conectando ao seu roadmap (e ao budget)

Essa mudança não exige reescrever a plataforma. É uma decisão de runtime mais disciplina operacional:

  • Decisão de runtime: Mapeie tiers para RuntimeClass e pools de nós. Use primeiro as opções gerenciadas da nuvem.
  • Disciplina operacional: Faça cumprir os padrões de segurança, aplique patches rapidamente e meça o overhead. Planeje um aumento de 5–10% no custo de compute para a fração de workloads que realmente precisam de isolamento mais forte.
  • Alinhamento com o negócio: Diga a produto e finanças: estamos reduzindo uma classe de riscos de cauda por dezenas de milhares por ano. Isso é mais barato do que uma violação com resposta a incidentes, créditos e erosão de confiança.

CopyFail não mudou a física dos contêineres; ele furou a narrativa de que “rootless é seguro o suficiente”. A resposta certa não é pânico. É clareza. Decida em qual código você realmente confia. Dê ao resto um sandbox de verdade. E pratique aplicar patch até ficar entediante.

Pontos‑chave

  • Rootless reduz o raio de impacto, mas não cria um sandbox do kernel. Trate-o como conveniência, não segurança, para código não confiável.
  • Use gVisor para Tier 1–2 e Kata/Firecracker para workloads Tier 2–3; orce 3–30% de overhead dependendo do workload.
  • Faça cumprir RuntimeClass, segurança de pods e regras de admissão para que os pods certos caiam no isolamento certo por padrão.
  • Fixe-se em kernels LTS, exercite um SLO de patch de 6–24 horas para CVEs de escape de contêiner e evite recursos exóticos do kernel de que você não precisa.
  • Espere +50–120 MB de RAM por sandbox do Kata e +150–400 ms de cold start; pré-aqueça ou faça pool para cumprir SLOs.
  • Assine imagens, use bases distroless e rejeite imagens com mais de 60 dias ou com arquivos setuid.
  • Meça o overhead do isolamento no seu próprio código; publique os números para que os times possam projetar em cima deles.

Ready to scale your engineering team?

Tell us about your project and we'll get back to you within 24 hours.

Start a conversation