Construindo um sandbox seguro e eficaz para viabilizar o Codex no Windows
Por David Wiesen, membro da equipe técnica
Quando entrei para a equipe de engenharia do Codex, em setembro de 2025, o Codex para Windows não tinha uma implementação de sandbox, o que obrigava usuários do Windows a escolher entre duas opções abaixo do ideal ao usar os agentes de programação da OpenAI:
- Aprovar quase todos os comandos (até leituras) que um agente de programação quisesse executar, o que é ineficiente e irritante. Um dos grandes benefícios de usar o Codex é que você não precisa fazer todo o trabalho tedioso por conta própria.
- Ativar o modo Full Access: permitir que o Codex execute todos os comandos sem aprovação nem restrições, o que elimina atrito às custas de supervisão.
Codex, nosso agente de programação, é executado nos laptops dos desenvolvedores, seja pela CLI, pela extensão de IDE ou pelo app para desktop. Ele gerencia uma conversa entre um humano no teclado e um modelo em execução na nuvem para lidar com a inferência.
Por padrão, o Codex é executado com as permissões de um usuário real, o que significa que ele pode fazer tudo o que o usuário pode fazer. Isso é poderoso e potencialmente perigoso. O modelo de programação pode instruir o harness a executar comandos localmente, desde rodar testes até ler ou editar um arquivo ou criar uma branch do Git, então o modo padrão do Codex tenta encontrar o equilíbrio certo entre eficácia e segurança. Esse modo padrão permite que o Codex leia arquivos em praticamente qualquer lugar e grave arquivos dentro do seu workspace (ou seja, o diretório em que você está executando o Codex), sem acesso à internet, a menos que você especifique que deseja esse acesso. Para aplicar automaticamente essas restrições de gravação de arquivos e acesso à rede dentro de limites seguros, o Codex precisa de um ambiente de sandbox que realmente imponha essas restrições.
Um sandbox é um ambiente de execução restrito. Quando um desenvolvedor usa o Codex, o sistema operacional do computador inicia um comando com permissões reduzidas, e essas restrições se propagam pela árvore de processos. Todo comando do Codex é executado em sandbox desde o início, e todo processo descendente permanece dentro do mesmo limite.
O Codex precisa de recursos de isolamento impostos pelo sistema operacional do computador para implementar um sandbox eficaz. Alguns sistemas operacionais oferecem utilitários que fazem isso bem (por exemplo, Seatbelt no macOS, seccomp ou bubblewrap no Linux); no entanto, atualmente o Windows não oferece esse tipo de capacidade pronta para uso.
Para tornar o Codex tão seguro e agradável de usar no Windows quanto já é em outros ambientes, precisávamos implementar nosso próprio sandbox.
O Windows oferece algumas ferramentas e primitivas para isolamento. Embora nenhuma delas atendesse totalmente aos nossos requisitos, analisamos várias soluções possíveis, especificamente AppContainer, Windows Sandbox e rotulagem de Mandatory Integrity Control.
AppContainer
- O que é: AppContainer é o sandbox nativo do Windows, um modelo de isolamento baseado em capacidades criado para aplicativos que sabem, de antemão, exatamente o que precisam acessar.
- Por que: Atraente porque oferece um limite real do sistema operacional em vez de restrições de melhor esforço.
- Por que não: o Codex não é um único app com escopo rigidamente delimitado. Ele conduz fluxos de trabalho abertos de desenvolvimento: shells, Git, Python, gerenciadores de pacotes, ferramentas de build e quaisquer outros binários que o agente decida que precisa usar. Na prática, isso tornou o AppContainer inadequado para o problema. Ele oferecia isolamento forte, mas para uma classe de cargas de trabalho muito mais estreita do que “deixar um agente operar como um desenvolvedor”.
Windows Sandbox
- O que é: o Windows Sandbox é a VM leve e descartável da Microsoft. Você recebe uma área de trabalho nova do Windows com um limite forte de isolamento, e tudo o que fizer dentro dela desaparece quando a sessão termina.
- Por que: Interessante por razões óbvias — muito mais compatível com software arbitrário do que o AppContainer e, do ponto de vista de segurança, uma caixa muito mais robusta.
- Por que não: o Codex precisa agir diretamente no checkout, nas ferramentas e no ambiente reais do usuário, não dentro de uma área de trabalho separada e descartável que exigiria configuração e ponte entre host e convidado. Ele também apresentava um problema fundamental de produto: o Windows Sandbox nem sequer está disponível nas SKUs do Windows Home.
Rotulagem de integridade do Mandatory Integrity Control (MIC)
- O que é: o Windows tem um conceito chamado “níveis de integridade”, como baixo, médio e alto, que determinam quanto o sistema confia em objetos e processos. A regra básica é que um processo de integridade mais baixa não pode gravar em um objeto com nível de integridade mais alto, mesmo que a ACL normal permitisse isso. Por exemplo, um processo de baixa integridade é tratado como menos confiável, então o Windows o impede de gravar em objetos normais de integridade média, a menos que esses objetos sejam explicitamente rerrotulados para permitir isso.
- Por quê: o MIC parecia elegante no papel: executar o Codex com baixa integridade, rerrotular as raízes graváveis como baixa integridade e deixar o Windows impor a ausência de gravação em todos os outros lugares. Isso teria nos dado um caminho sem privilégios de administrador, com um mecanismo real do sistema operacional por trás.
- Por que não: assim como as ACLs, os rótulos de integridade modificam o sistema de arquivos real do host e, neste caso, a mudança semântica é especialmente ampla. Marcar um workspace como baixa integridade não significa apenas “o Codex pode gravar aqui”. Significa que processos de baixa integridade em geral podem gravar ali. Em uma máquina real de desenvolvimento, isso transforma o checkout real do usuário em um destino de baixa integridade para o host, o que é muito mais arriscado do que conceder ACLs cuidadosamente direcionadas a um único design de sandbox. Mesmo que ferramentas de desenvolvimento de integridade média continuem funcionando, o modelo de confiança subjacente do workspace foi alterado de uma forma difícil de conter e ainda mais difícil de justificar.
Depois de avaliar todas as opções como inviáveis, começamos a projetar nossa própria solução para oferecer uma boa experiência com o Codex aos usuários do Windows.
Nosso primeiro protótipo funcional usou uma combinação de conceitos e ferramentas do Windows para implementar o isolamento de que precisávamos. Desde o início, um dos objetivos era fazer isso funcionar sem exigir elevação, ou seja, sem que o Codex precisasse pedir privilégios de administrador ao usuário apenas para configurar ou executar o sandbox. Isso significava descobrir como impor limites razoáveis a duas coisas: gravações em arquivos e acesso à rede.
Se não limitássemos as gravações em arquivos, teríamos um problema de segurança. Se limitássemos demais as gravações em arquivos, o sandbox prejudicaria a produtividade do usuário, exigindo aprovações constantes. Para resolver esse problema, nos apoiamos em dois componentes importantes do Windows: SIDs e tokens com restrição de escrita.
Um SID, ou identificador de segurança, é a identidade que o Windows associa a permissões. Cada usuário tem um SID, grupos têm SIDs e até uma única sessão de login recebe seu próprio SID. Por exemplo, uma sessão atualmente conectada pode ter um SID como S-1-5-5-X-Y. O SID atribuído ao grupo local de administradores pode ser S-1-5-32-544.
O Windows também permite criar SIDs sintéticos que não correspondem a um usuário real, mas ainda podem aparecer em ACLs (listas de controle de acesso), que definem quem pode ler/gravar/executar arquivos ou diretórios específicos. Isso torna os SIDs uma primitiva útil para nosso sandbox: podemos criar SIDs exclusivamente para uso pelo sandbox do Codex, sem interferir em mais nada na máquina.
Tokens de processo são objetos de segurança no Windows que definem identidade e privilégios para um processo em execução. Eles determinam quais ações um processo pode realizar. Um token com restrição de escrita é um tipo específico de token de processo que faz o Windows realizar uma verificação adicional de acesso em operações de gravação.
Para que uma gravação seja bem-sucedida, duas verificações precisam passar:
- A identidade normal do usuário (o “proprietário” do token) precisa ter permissão para fazê-la
- Pelo menos um SID na lista de SIDs restritos do token também precisa receber acesso
Na prática, essas verificações nos permitem usar ACLs para definir exatamente onde o sandbox poderia modificar o sistema de arquivos, oferecendo a granularidade de que precisávamos em torno das operações de gravação.
Com SIDs e tokens com restrição de escrita, nosso sandbox sem elevação funcionava assim:
- A configuração do sandbox criava um SID sintético chamado
sandbox-write. - O SID
sandbox-writerecebia acesso de gravação, execução e exclusão a- O diretório de trabalho atual
- Quaisquer
writable_rootsadicionais configuradas emconfig.toml.
- A configuração do sandbox negava explicitamente a esse mesmo SID acesso de gravação a locais “somente leitura dentro de graváveis”, como:
<cwd>/.git<cwd>/.codex<cwd>/.agents
- O Codex iniciava comandos sob um token com restrição de gravação cuja lista de SIDs restritos inclui
Everyone, o SID da sessão atual conectada e o SID sintéticosandbox-write.
Esse fluxo resolveu efetivamente a limitação de gravações em arquivos e parecia promissor. Agora precisávamos de uma solução para limitar o acesso à rede do sandbox.
Limitar o acesso à rede é uma parte importante do sandbox; sem isso, código malicioso poderia exfiltrar dados da máquina para a internet. Como queríamos evitar a exigência de elevação, tínhamos opções limitadas para bloquear fortemente o tráfego de rede. As ferramentas que queríamos usar, como o Windows Firewall, em geral não podiam ser instaladas sem permissões de administrador.
Sem o Windows Firewall como opção, limitamos o que podíamos controlar. Tentamos fazer o ambiente filho falhar em modo fechado para os tipos de ferramentas em rede que desenvolvedores realmente usam, de modo que comandos Git, instaladores de pacotes etc. falhassem no sandbox e o usuário precisasse aprovar qualquer operação voltada à internet. A ideia era envenenar as rotas de fuga óbvias: enviar tráfego sensível a proxy para um endpoint morto, fazer o transporte HTTP(S) do Git fazer o mesmo e fazer Git via SSH falhar imediatamente. Além disso, prefixamos um pequeno diretório denybin ao PATH e reordenamos PATHEXT para que scripts stub de SSH e SCP fossem resolvidos antes dos binários reais.
Por exemplo, aqui estão algumas das substituições específicas de ambiente que usamos para limitar o acesso à rede:
HTTPS_PROXY=http://127.0.0.1:9ALL_PROXY=http://127.0.0.1:9GIT_HTTPS_PROXY=http://127.0.0.1:9NO_PROXY=localhost,127.0.0.1,::1GIT_SSH_COMMAND=cmd /c exit 1
Isso capturou muito tráfego normal gerado por ferramentas, mas ainda era apenas uma orientação. Um processo poderia ignorar o ambiente, contornar o PATH ou simplesmente abrir sockets diretamente — arriscado demais.
Como em qualquer implementação de software interessante, o primeiro protótipo tinha alguns prós e contras. Embora fizesse o trabalho usando apenas alguns recursos padrão do Windows, permitisse gravações no sistema de arquivos muito explícitas e granulares e rodasse sem elevação — eliminando a necessidade de usuários aceitarem prompts excessivos de elevação ou serem administradores na própria máquina — ele tinha desvantagens reais, algumas das quais o desqualificaram como nosso design final:
- Velocidade de configuração: aplicar ACLs ao workspace pode ser custoso, dependendo da topologia do diretório do workspace.
- Pegada: aplicamos ACLs reais ao sistema do desenvolvedor, embora a pegada não seja particularmente invasiva porque todas as ACLs aplicadas dizem respeito a um SID sintético personalizado, usado apenas pelo sandbox.
- Semântica difícil de alterar: a dependência de ACLs para restrições baseadas em arquivos torna caro e complexo alterar a semântica do sandbox. Enquanto no macOS podemos alterar dinamicamente como geramos o arquivo
.sbplusado para configurar o Seatbelt, o sandbox do Windows poderia exigir uma operação lenta e intensa para ajustar ACLs. - A proteção de rede é fraca. Como mencionado antes, ela era “orientativa”, certamente seria contornada por alguns programas que implementassem a própria stack de rede e não foi projetada para resistir a código adversarial.
Os três primeiros problemas são inerentes a uma implementação personalizada de sandbox flexível o suficiente para fluxos agênticos. A história da supressão de rede, porém, era diferente.
Além de um agente malicioso conseguir contornar facilmente a supressão de rede baseada em ambiente, muitos códigos/binários bem-intencionados também a contornariam simplesmente por não respeitarem as variáveis de proxy do ambiente ou por implementarem o próprio código de rede baseado em sockets. Sentimos que esse aspecto era suficiente para considerar investir em um modo de sandbox melhor.
Para obter melhor supressão de rede, queríamos usar o Windows Firewall, que permite bloquear tráfego de rede de saída para usuários ou programas. Infelizmente, não conseguíamos criar de forma eficaz uma regra funcional de firewall que se aplicasse apenas aos comandos gerados pelo harness do Codex por alguns motivos:
- O Windows não permite associar uma regra de firewall à identidade não principal de um token restrito. Isso significa que não podíamos aplicar uma regra de firewall a “qualquer token que inclua nosso SID sintético em sua lista de SIDs restritos”.
- Embora pudéssemos criar uma regra de firewall que correspondesse a um binário específico, isso só nos permitiria limitar a rede para o próprio
codex.exe. Ela não se aplicaria aos processos que o agente gera em nome do usuário, como processos Git ou Python. - Outras dimensões de correspondência do firewall também tinham o formato errado. Regras com escopo de usuário ainda correspondiam ao usuário real do Windows no design sem elevação, não apenas ao filho restrito. Regras por caminho de programa eram amplas demais: podiam bloquear
codex.exeoupython.exede forma geral, mas não esta invocação específica em sandbox depython.exe. Regras baseadas em porta ou endereço também eram a política errada. Por exemplo, não queríamos bloquear a porta 443; queríamos bloquear acesso arbitrário de saída para esta árvore específica de processos restritos.
Para aplicar uma regra de firewall especificamente aos nossos comandos em sandbox, precisávamos executá-los como um principal separado, não como o usuário “real”. Essa abordagem nos levou a um novo caminho, em que flexibilizamos nossa restrição de “sem elevação”.
A próxima iteração do sandbox, que é nossa implementação atual, exige permissões elevadas de administrador no momento da configuração. Por isso, refiro-me a ela como “o sandbox com elevação”. No limite em que o Codex gera um comando no sistema, o sandbox com elevação se parece com o sem elevação. Ele ainda executa processos filhos sob um token restrito — de modo semelhante, um token write_restricted com a mesma lista de SIDs restritos de [Everyone, Logon, Synthetic]—porém, o principal desse token não é mais o usuário real do Windows, e sim um de dois usuários locais criados pelo próprio Codex:
CodexSandboxOffline(o que é alvo das regras de firewall)CodexSandboxOnline(o que não é alvo das regras de firewall)
Esse detalhe aparentemente pequeno, na verdade, tem grandes implicações para o sandbox, para quem pode usá-lo e para a complexidade da sua configuração e execução em runtime.
Visualmente, ele é semelhante ao protótipo sem elevação, com a introdução de regras de firewall e de um usuário dedicado do Windows, que é quem realmente executa os comandos. (No entanto, a introdução desses novos conceitos significa que há mais trabalho de configuração a fazer antes que o sandbox possa começar a executar e proteger comandos.)
O design do sandbox sem elevação tinha uma etapa de configuração simples, mas relativamente pequena:
- Criar um SID sintético se necessário
- Aplicar ACLs para o SID sintético sandbox-write
O sandbox com elevação, porém, tem mais trabalho a fazer.
- Criar um SID sintético, se ainda não tiver sido criado
- Criar os usuários online e offline do sandbox, se ainda não tiverem sido criados
- Armazenar localmente as credenciais dos usuários recém-criados e criptografá-las usando a Windows Data Protection API (DPAPI), em um local que os usuários do sandbox não consigam ler de fato
- Criar regras de firewall que bloqueiem todo o tráfego de rede de saída para o usuário
CodexSandboxOfflineou, se elas já existirem, validar que estão corretas
Há uma complicação adicional na etapa de configuração. Espera-se que o sandbox do Codex tenha acesso de leitura equivalente ao do usuário real do Windows. No sandbox sem elevação, em que o SID principal do token restrito era o usuário do Windows, isso era alcançado. No entanto, isso não vem de graça quando o principal passa a ser um novo usuário CodexSandbox. Muitos diretórios relevantes no Windows concedem permissões de leitura/execução a “Usuários autenticados”. Um exemplo notável é o diretório de perfil do usuário. Por padrão, usuários do Windows não conseguem ler os diretórios de perfil de outros usuários do Windows, então até leituras simples de arquivos falhariam em muitos cenários.
Para resolver isso, adicionamos outra camada ao processo de configuração do sandbox: uma para conceder ACLs de leitura aos usuários do sandbox onde essas ACLs talvez ainda não existissem. Por exemplo, em alguns diretórios do Windows usados com frequência:
C:\Users\<real-user>C:\Windows\C:\Program Files\C:\Program Files (x86)\C:\ProgramData\
Como essa lista de diretórios é baseada em melhor esforço e instalar ACLs em cada um deles pode ser bastante custoso, executamos essa lógica de forma assíncrona para que a etapa de configuração do sandbox, que bloqueia os usuários, não precise esperar sua conclusão.
Encapsulamos a lógica de configuração em seu próprio binário, em parte para cruzar o limite do UAC apenas quando necessário. Mas o motivo mais profundo era arquitetural: a configuração do sandbox tem uma função fundamentalmente diferente da de codex.exe. Manter a lógica de configuração do sandbox em um binário dedicado permitiu que codex.exe continuasse sendo um harness normal, sem elevação; evitou que a maquinaria de configuração específica do Windows inchasse o codex.exe em outras plataformas; desacoplou trabalhos de configuração mais longos do ciclo de vida do processo principal; e nos deu um único lugar para lidar com os diferentes caminhos de configuração de que o sandbox precisava.
Devido à forma como os limites de login de usuários e tokens funcionam no Windows, não podíamos continuar criando um token restrito e iniciando um processo sob ele da mesma forma que fazíamos com o sandbox sem elevação. Para realmente iniciar comandos como um usuário diferente do Windows, nossa primeira ideia foi o seguinte fluxo:
codex.exeé executado como o usuário real do Windows. Então, em sequência, o Codex:- Chama
LogonUserW(...)para o usuário da sandbox. - Chama
CreateRestrictedToken(...)nesse token de usuário de sandbox. - Usando esse token restrito de usuário de sandbox, chama
CreateProcessAsUserW(...)para iniciar o processo filho final.
- Chama
Na prática, esse fluxo desejado não funcionou por causa de uma barreira de privilégio em CreateProcessAsUserW(...). Isso significa que codex.exe conseguia criar um token restrito para o usuário do sandbox, mas não conseguia iniciar de forma confiável um processo filho com esse token a partir do lado do limite do usuário real. Precisávamos de um processo que já estivesse em execução como o usuário do sandbox; isso permitiria que a etapa de restrição e a geração final do processo acontecessem do lado do limite do usuário do sandbox, em vez de acontecerem do lado do usuário real.
Esse requisito levou ao codex-command-runner.exe, um novo binário cuja única função é criar um token restrito e iniciar o comando solicitado. Em vez de pedir que codex.exe fizesse todo o fluxo sozinho (usuário real → usuário do sandbox → token restrito → processo filho), dividimos o fluxo em duas partes:
Parte 1
codex.exechamaCreateProcessWithLogonW(...)para iniciar ocodex-command-runner.execomo o usuário do sandbox, sem usar um token restrito ainda.
Parte 2
- Dentro do runner,
OpenProcessToken(GetCurrentProcess(), ...)abre o token do próprio runner, que já pertence ao usuário do sandbox. - O runner chama
GetTokenInformation(...)para extrair o SID de logon do sandbox, depoisCreateRestrictedToken(...)para construir o token restrito final. - Ainda dentro do runner, ele chama
CreateProcessAsUserW(...)com esse token restrito para iniciar o verdadeiro processo filho.
Albert Einstein disse: “Tudo deve ser feito da forma mais simples possível, mas não mais simples que isso.” Nesse espírito, nosso design resolveu adequadamente cada problema. A arquitetura final tem as quatro camadas que abordamos anteriormente:
- o próprio
codex.exe codex-windows-sandbox-setup.exepara lidar com todo o trabalho de configuração elevada relacionadocodex-command-runner.exepara executar comandos com token restrito- O processo filho
Quando comecei a trabalhar neste projeto, eu não tinha uma noção clara de onde ele chegaria. Minha abordagem foi começar instrumentando a capacidade de sandboxing no limite entre o Codex e o sistema operacional. Essa abordagem corresponde de perto à forma como o sandbox do Codex é implementado no macOS e no Linux.
À medida que aprendi mais sobre as ferramentas específicas que o Windows oferece, e ao longo de dezenas de decisões equilibrando segurança e facilidade de uso, o sistema cresceu até sua forma atual: múltiplos binários, usuários personalizados, regras de firewall, uma etapa de configuração com elevação, processos assíncronos e muito mais.
Não é um sistema particularmente simples, mas cada peça de complexidade foi adicionada por necessidade, para criar um sandbox que seja seguro e, tanto quanto possível, não atrapalhe o usuário.
Ao trabalhar para oferecer uma boa experiência aos usuários do Codex no Windows, nosso objetivo era criar algo seguro sem comprometer a utilidade; afinal, o objetivo de usar o Codex é permitir que agentes façam trabalho sem exigir sua atenção constante.
Uma das maiores lições deste projeto foi que o Windows não nos entregou uma primitiva única que mapeasse de forma limpa para “agente de programação autônomo seguro”. Combinamos várias ferramentas e conceitos para criar algo coerente. Algumas ideias iniciais foram becos sem saída. O design final foi um híbrido de protótipos anteriores, cada um dos quais resolvia parte do problema.
A outra lição foi que segurança para um agente de programação é uma fera diferente da segurança de aplicações mais clássica. O Codex precisa funcionar para fluxos de trabalho reais de desenvolvedores. O trabalho de engenharia foi equilibrar compatibilidade com cargas de trabalho agênticas e aplicação real de restrições. Essa tensão moldou os tradeoffs no design final.
Quer ver o sandbox do Codex em ação? Experimente.


