Saltar para o conteúdo principal
OpenAI

13 de maio de 2026

EngenhariaGarantia

Criar uma sandbox segura e eficaz para disponibilizar o Codex no Windows

Por David Wiesen, membro da equipa técnica

A carregar…

Quando entrei para a equipa de engenharia do Codex, em setembro de 2025, o Codex para Windows não tinha uma implementação de sandbox, o que obrigava os utilizadores de Windows a escolher entre duas opções pouco ideais ao usar os agentes de programação da OpenAI:

  1. Aprovar quase todos os comandos (até leituras) que um agente de programação queria executar, o que é ineficiente e incómodo. Uma das grandes vantagens de usar o Codex é não ter de fazer todo o trabalho aborrecido por si.
  2. Ativar o modo Full Access: permitir que o Codex execute todos os comandos sem aprovação nem restrições, o que remove fricção à custa da supervisão.

Codex, o nosso agente de programação, é executado nos portáteis dos programadores — seja através da CLI, da extensão do IDE ou da aplicação de desktop. Gere uma conversa entre uma pessoa ao teclado e um modelo em execução na cloud para tratar da inferência.

Por predefinição, o Codex é executado com as permissões de um utilizador real, o que significa que pode fazer tudo o que o utilizador pode fazer. Isto é poderoso e potencialmente perigoso. O modelo de programação pode instruir o harness a executar comandos localmente, desde executar testes até ler ou editar um ficheiro ou criar uma branch do Git, pelo que o modo predefinido do Codex tenta encontrar o equilíbrio certo entre eficácia e segurança. Este modo predefinido permite ao Codex ler ficheiros praticamente em qualquer lugar e escrever ficheiros dentro do seu espaço de trabalho (ou seja, o diretório onde está a executar o Codex), sem acesso à internet, a menos que especifique que o pretende. Para alcançar esta restrição automática de escrita de ficheiros e acesso à rede dentro de limites seguros, o Codex precisa de um ambiente de sandbox que realmente aplique estas restrições.

Uma sandbox é um ambiente de execução restringido. Quando um programador usa o Codex, o sistema operativo do computador inicia um comando com permissões reduzidas, e essas restrições propagam-se pela árvore de processos. Todos os comandos do Codex são colocados em sandbox desde o início, e todos os processos descendentes permanecem dentro do mesmo limite.

Diagrama que mostra os limites de isolamento ao nível do sistema operativo da sandbox do Codex.

O Codex precisa de funcionalidades de isolamento aplicadas pelo sistema operativo do computador para implementar uma sandbox eficaz. Alguns sistemas operativos disponibilizam utilitários que fazem isto bem (por exemplo, Seatbelt no macOS, seccomp ou bubblewrap no Linux); no entanto, atualmente o Windows não disponibiliza este tipo de capacidade de origem.

Para tornar o Codex tão seguro e agradável de usar no Windows como já é em todos os outros ambientes, precisámos de implementar a nossa própria sandbox.

Onde as ferramentas Windows existentes ficaram aquém

O Windows oferece algumas ferramentas e primitivas de isolamento. Embora nenhuma cumprisse exatamente os nossos requisitos, analisámos várias soluções potenciais, nomeadamente AppContainer, Windows Sandbox e rotulagem de integridade Mandatory Integrity Control.

AppContainer

  • O que é: O AppContainer é a sandbox nativa do Windows, um modelo de isolamento baseado em capacidades criado para aplicações que sabem, à partida, exatamente a que precisam de aceder.
  • Porquê: Atrativo porque oferece um verdadeiro limite ao nível do sistema operativo em vez de restrições por melhor esforço.
  • Porque não: o Codex não é uma aplicação única com âmbito bem delimitado. Impulsiona fluxos de trabalho abertos de programadores: shells, Git, Python, gestores de pacotes, ferramentas de build e quaisquer outros binários que o agente decida que precisa. Na prática, isso fez com que o AppContainer não fosse adequado para o problema. Oferecia isolamento forte, mas para uma classe de cargas de trabalho muito mais restrita do que «deixar um agente operar como um programador».

Windows Sandbox

  • O que é: o Windows Sandbox é a VM leve e descartável da Microsoft. Obtém um desktop Windows novo, com um limite de isolamento forte, e tudo o que fizer dentro dele desaparece quando a sessão termina.
  • Porquê: Interessante por razões óbvias — muito mais compatível com software arbitrário do que o AppContainer e, do ponto de vista da segurança, um isolamento muito mais forte.
  • Porque não: o Codex precisa de agir diretamente no checkout, nas ferramentas e no ambiente reais do utilizador, e não dentro de um desktop separado e descartável que exigiria configuração e ponte entre host e convidado. Também tinha um problema fundamental de produto: o Windows Sandbox nem sequer está disponível nas SKUs Windows Home.

Rotulagem de integridade Mandatory Integrity Control (MIC)

  • O que é: o Windows tem um conceito chamado «níveis de integridade», como baixo, médio e alto, que determinam em que medida o sistema confia em objetos e processos. A regra básica é que um processo de menor integridade não pode escrever num objeto com um nível de integridade mais alto, mesmo que a ACL normal o permitisse de outra forma. Por exemplo, um processo de baixa integridade é tratado como menos fiável, pelo que o Windows o impede de escrever em objetos normais de integridade média, a menos que esses objetos sejam explicitamente reclassificados para o permitir.
  • Porquê: o MIC parecia elegante no papel — executar o Codex com baixa integridade, reclassificar as raízes graváveis como baixa integridade e deixar o Windows impor a regra de não escrita em todos os outros lugares. Isso ter-nos-ia dado um caminho sem privilégios de administrador, com um mecanismo real do sistema operativo por trás.
  • Porque não: tal como as ACLs, os rótulos de integridade modificam o sistema de ficheiros real do host e, neste caso, a alteração semântica é especialmente ampla. Marcar um espaço de trabalho como de baixa integridade não significa apenas «o Codex pode escrever aqui». Significa que processos de baixa integridade em geral podem escrever aí. Numa máquina real de um programador, isso transforma o checkout real do utilizador num 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 as ferramentas de programador de integridade média continuem a funcionar, o modelo de confiança subjacente do espaço de trabalho foi alterado de uma forma difícil de conter e ainda mais difícil de justificar.

Depois de avaliarmos todas as opções e as considerarmos inviáveis, começámos a desenhar a nossa própria solução para proporcionar uma boa experiência do Codex aos utilizadores de Windows.

O primeiro protótipo: a «sandbox sem elevação»

O 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 isto sem exigir elevação, ou seja, sem que o Codex precisasse de pedir privilégios de administrador ao utilizador apenas para configurar ou executar a sandbox. Isso implicava descobrir como impor limites razoáveis a duas coisas: escrita de ficheiros e acesso à rede.

Limitar a escrita de ficheiros

Se não limitássemos de todo a escrita de ficheiros, teríamos um problema de segurança. Se limitássemos demasiado a escrita de ficheiros, a sandbox prejudicaria a produtividade dos utilizadores, tendo de pedir aprovação constante. Para resolver este problema, recorremos a dois blocos de construção importantes do Windows: SIDs e tokens com escrita restrita.

Os SIDs permitem-nos dar uma identidade à sandbox

Um SID, ou identificador de segurança, é a identidade que o Windows associa a permissões. Cada utilizador tem um SID, os grupos têm SIDs, e até uma única sessão de início de sessão recebe o seu próprio SID. Por exemplo, uma sessão atualmente iniciada 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 utilizador real, mas que ainda podem aparecer em ACLs (listas de controlo de acesso), que definem quem pode ler/escrever/executar ficheiros ou diretórios específicos. Isto torna os SIDs uma primitiva útil para a nossa sandbox: podemos criar SIDs exclusivamente para utilização pela sandbox do Codex, sem interferir com mais nada na máquina.

Os tokens com escrita restrita limitam onde o Codex pode modificar ficheiros

Os tokens de processo são objetos de segurança no Windows que definem a identidade e os privilégios de um processo em execução. Determinam que ações um processo pode realizar. Um token com escrita restrita é um tipo específico de token de processo que faz com que o Windows realize uma verificação de acesso adicional nas operações de escrita.

Para que uma escrita seja bem-sucedida, duas verificações têm de passar:

  1. A identidade normal do utilizador (o «proprietário» do token) tem de estar autorizada a fazê-lo
  2. Pelo menos um SID na lista de SIDs restritos do token também tem de ter acesso concedido
Diagrama intitulado A escrita na sandbox requer acesso normal de utilizador e acesso SID sandbox-write.

Na prática, estas verificações permitem-nos usar ACLs para definir exatamente onde a sandbox pode modificar o sistema de ficheiros, oferecendo a granularidade de que precisávamos em torno das operações de escrita.

Com SIDs e tokens com escrita restrita, a nossa sandbox sem elevação funcionava assim:

  1. A configuração da sandbox criou um SID sintético chamado sandbox-write.
  2. O SID sandbox-write recebia acesso de escrita, execução e eliminação a
    1. O diretório de trabalho atual
    2. Quaisquer writable_roots adicionais configuradas em config.toml.
  3. A configuração da sandbox negava explicitamente a esse mesmo SID acesso de escrita a localizações «só de leitura dentro de graváveis», tais como:
    1. <cwd>/.git
    2. <cwd>/.codex
    3. <cwd>/.agents
  4. O Codex lançava comandos sob um token com restrição de escrita cuja lista de SIDs restritos inclui Everyone, o SID da sessão atualmente iniciada e o SID sintético sandbox-write.

Este fluxo resolvia eficazmente a limitação das escritas de ficheiros e parecia promissor. Agora precisávamos de uma solução para limitar o acesso da sandbox à rede.

Limitar o acesso à rede

Limitar o acesso à rede é uma parte importante da sandbox; sem isso, código malicioso poderia exfiltrar dados da máquina para a internet. Como queríamos evitar um requisito de elevação, tínhamos opções limitadas para bloquear tráfego de rede de forma robusta. As ferramentas que queríamos usar, como o Windows Firewall, geralmente não podiam ser instaladas sem permissões de administrador.

Sem o Windows Firewall como opção, limitámos aquilo que conseguíamos controlar. Tentámos fazer com que o ambiente filho falhasse de forma fechada para os tipos de ferramentas com rede que os programadores realmente usam, para que comandos Git, instaladores de pacotes, etc., falhassem na sandbox e o utilizador tivesse de aprovar quaisquer operações viradas para a internet. A ideia era inutilizar as vias de fuga óbvias: enviar tráfego compatível com proxy para um endpoint inativo, fazer com que o transporte HTTP(S) do Git fizesse o mesmo e fazer com que o Git via SSH falhasse imediatamente. Além disso, adicionámos no início do PATH um pequeno diretório denybin e reordenámos PATHEXT para que scripts stub de SSH e SCP fossem resolvidos antes dos binários reais.

Por exemplo, eis algumas das substituições específicas de ambiente que usámos para limitar o acesso à rede:

  • HTTPS_PROXY=http://127.0.0.1:9
  • ALL_PROXY=http://127.0.0.1:9
  • GIT_HTTPS_PROXY=http://127.0.0.1:9
  • NO_PROXY=localhost,127.0.0.1,::1
  • GIT_SSH_COMMAND=cmd /c exit 1
Diagrama que mostra a arquitetura da sandbox elevada com regras de firewall e um utilizador Windows dedicado.

Isto apanhava muito tráfego normal gerado por ferramentas, mas continuava a ser apenas indicativo. Um processo podia ignorar o ambiente, contornar o PATH ou simplesmente abrir sockets diretamente — demasiado arriscado.

A abordagem sem elevação implicava compromissos

Como em qualquer implementação de software interessante, o primeiro protótipo tinha alguns prós e contras. Embora cumprisse o objetivo usando apenas algumas capacidades standard do Windows, permitisse escritas no sistema de ficheiros muito explícitas e granulares, e fosse executado sem elevação — eliminando a necessidade de os utilizadores aceitarem prompts excessivos de elevação ou de serem administradores na máquina local — tinha algumas desvantagens reais, algumas das quais o desqualificaram como design final:

  • Velocidade de configuração: aplicar ACLs ao espaço de trabalho pode ser dispendioso, dependendo da topologia do diretório do espaço de trabalho.
  • Pegada: aplicámos ACLs reais ao sistema do programador, embora a pegada não seja particularmente invasiva porque todas as ACLs aplicadas dizem respeito a um SID sintético criado à medida e usado apenas pela sandbox.
  • Semântica difícil de alterar: a dependência de ACLs para restrições baseadas em ficheiros significa que alterar a semântica da sandbox é dispendioso e complexo. Enquanto no macOS podemos alterar dinamicamente a forma como geramos o ficheiro .sbpl usado para configurar o Seatbelt, a sandbox do Windows podia exigir uma operação lenta e intensa para ajustar ACLs.
  • A proteção de rede é fraca. Como referido anteriormente, era «indicativa», seria certamente contornada por alguns programas que implementassem a sua própria stack de rede, e não foi concebida para resistir a código adversarial.

Os três primeiros problemas são inerentes a uma implementação personalizada de sandbox suficientemente flexível para fluxos agênticos. A história da supressão de rede era diferente.

A supressão de rede é demasiado importante

Além de um agente malicioso conseguir contornar facilmente a supressão de rede baseada no ambiente, muito código/binários bem-intencionados também a contornariam simplesmente se não respeitassem as variáveis de proxy do ambiente, ou se implementassem o seu próprio código de rede baseado em sockets. Considerámos que este aspeto era suficiente para justificar o investimento num modo de sandbox melhor.

Para conseguir uma melhor supressão de rede, queríamos usar o Windows Firewall, que nos permite bloquear tráfego de rede de saída para utilizadores ou programas. Infelizmente, não conseguíamos criar de forma eficaz uma regra de firewall funcional 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. Isto significa que não conseguíamos aplicar uma regra de firewall a «qualquer token que inclua o nosso SID sintético na respetiva 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. Não se aplicaria aos processos que o agente gera em nome do utilizador, como processos Git ou Python.
  • Outras dimensões de correspondência da firewall também não tinham o formato certo. Regras com âmbito de utilizador continuavam a corresponder ao utilizador real do Windows no design sem elevação, e não apenas ao filho restrito. Regras por caminho de programa eram demasiado grosseiras: podiam bloquear codex.exe ou python.exe de forma geral, mas não esta invocação específica em sandbox de python.exe. Regras baseadas em porta ou endereço também eram uma política totalmente inadequada. Por exemplo, não queríamos bloquear a porta 443; queríamos bloquear o acesso arbitrário de saída para esta árvore de processos restrita específica.

Para aplicar uma regra de firewall especificamente aos nossos comandos em sandbox, precisávamos de os executar como um principal separado, e não como o utilizador «real». Esta abordagem levou-nos por um novo caminho, no qual relaxámos a nossa restrição de «sem elevação».

O redesenho: a «sandbox elevada»

A iteração seguinte da sandbox, que é a nossa implementação atual, exige permissões elevadas de administrador no momento da configuração. Por isso, refiro-me a ela como «a sandbox elevada». No limite em que o Codex gera um comando no sistema, a sandbox elevada é parecida com a versão sem elevação. Continua a executar processos filhos sob um token restrito — de forma semelhante, um token write_restricted com a mesma lista de SIDs restritos [Everyone, Logon, Synthetic]—contudo, o principal deste token já não é o utilizador real do Windows, mas um de dois utilizadores locais criados pelo próprio Codex:

  • CodexSandboxOffline (visado pelas regras da firewall)
  • CodexSandboxOnline (o não visado pelas regras da firewall)

Este detalhe aparentemente pequeno tem, na verdade, grandes implicações para a sandbox, para quem a pode usar e para a complexidade da sua configuração e execução em tempo de execução.

Diagrama que mostra as substituições do ambiente de rede para a sandbox não elevada.

É visualmente semelhante ao protótipo sem elevação, com a introdução de regras de firewall e de um utilizador Windows dedicado, que é quem realmente executa os comandos. (No entanto, a introdução destes novos conceitos significa que há mais trabalho de configuração a fazer antes de a sandbox poder começar a executar e proteger comandos.)

Agora precisamos de um passo de configuração de primeira classe

O design da sandbox sem elevação tinha um passo de configuração simples, mas relativamente pequeno:

  • Criar um SID sintético, se necessário
  • Aplicar ACLs para o SID sintético sandbox-write

A sandbox elevada, no entanto, tem mais trabalho a fazer.

  • Criar um SID sintético, caso ainda não tenha sido criado
  • Criar os utilizadores online e offline da sandbox, caso ainda não tenham sido criados
  • Guardar localmente as credenciais dos utilizadores recém-criados e encriptá-las usando a Windows Data Protection API (DPAPI), num local que os utilizadores da sandbox não consigam realmente ler
  • Criar regras de firewall que bloqueiem todo o tráfego de rede de saída para o utilizador CodexSandboxOffline ou, se já existirem, validar que estão corretas

Há uma complexidade adicional na fase de configuração. Espera-se que a sandbox do Codex tenha acesso de leitura equivalente ao do utilizador Windows real. Na sandbox sem elevação, em que o SID principal do token restrito era o utilizador Windows, isto era alcançado. No entanto, isso não acontece automaticamente quando o principal passa a ser um novo utilizador CodexSandbox. Muitos diretórios relevantes no Windows concedem permissões de leitura/execução a «Utilizadores Autenticados». Um exemplo notável é o diretório de perfil do utilizador. Por predefinição, os utilizadores Windows não conseguem ler os diretórios de perfil de outros utilizadores Windows, pelo que até simples leituras de ficheiros falhariam em muitos cenários.

Para resolver isto, adicionámos outra camada ao processo de configuração da sandbox — uma camada para conceder ACLs de leitura aos utilizadores da sandbox onde essas ACLs possam ainda não existir. Por exemplo, em alguns diretórios Windows frequentemente utilizados:

  • C:\Users\<real-user>
  • C:\Windows\
  • C:\Program Files\
  • C:\Program Files (x86)\
  • C:\ProgramData\

Como esta lista de diretórios é baseada no melhor esforço e instalar ACLs em cada um deles pode ser bastante dispendioso, executamos esta lógica de forma assíncrona para que o passo de configuração da sandbox, que bloqueia os utilizadores, não tenha de esperar pela conclusão.

Encapsulámos a lógica de configuração no seu próprio binário, em parte para atravessar o limite da UAC apenas quando necessário. Mas o motivo mais profundo era arquitetural: a configuração da sandbox tem uma função fundamentalmente diferente da do codex.exe. Manter a lógica de configuração da sandbox num binário dedicado permitiu que o codex.exe continuasse a ser um harness normal, sem elevação; impediu que a maquinaria de configuração específica do Windows aumentasse desnecessariamente o codex.exe noutras plataformas; desacoplou trabalho de configuração mais demorado do ciclo de vida do processo principal; e deu-nos um único local para gerir os diferentes caminhos de configuração de que a sandbox precisava.

Diagrama que mostra a etapa inicial de configuração da sandbox elevada.

O executor de comandos é um novo binário que executa efetivamente comandos do utilizador

Devido à forma como funcionam os limites de início de sessão de utilizadores e tokens no Windows, não podíamos continuar a criar um token restrito e a gerar um processo sob esse token como fazíamos com a sandbox sem elevação. Para gerar efetivamente comandos como outro utilizador Windows, a nossa primeira ideia foi o seguinte fluxo:

  • codex.exe é executado como o utilizador Windows real. Depois, numa sequência, o Codex:
    • Chama LogonUserW(...) para o utilizador da sandbox.
    • Chama CreateRestrictedToken(...) nesse token de utilizador da sandbox.
    • Utilizando esse token de utilizador de sandbox restrito, chama CreateProcessAsUserW(...) para iniciar o processo filho final.

Na prática, esse fluxo pretendido não funcionou devido a uma barreira de privilégios em CreateProcessAsUserW(...). Isto significa que o codex.exe conseguia criar um token restrito para o utilizador da sandbox, mas não conseguia lançar de forma fiável um processo filho com esse token a partir do lado do limite correspondente ao utilizador real. Precisávamos de um processo que já estivesse a ser executado como o utilizador da sandbox — isto permitiria que o passo de restrição e a geração final acontecessem do lado do limite correspondente ao utilizador da sandbox, e não do lado do utilizador real.

Esse requisito levou ao codex-command-runner.exe, um novo binário cuja única função é criar um token restrito e gerar o comando solicitado. Em vez de pedir ao codex.exe que realizasse todo o fluxo sozinho (utilizador real → utilizador da sandbox → token restrito → processo filho), dividimos o fluxo em duas partes:

Parte 1

  • O codex.exe chama CreateProcessWithLogonW(...) para lançar codex-command-runner.exe como o utilizador da sandbox, sem ainda usar um token restrito.

Parte 2

  • Dentro do runner, OpenProcessToken(GetCurrentProcess(), ...) abre o token do próprio runner, que já pertence ao utilizador da sandbox.
  • O runner chama GetTokenInformation(...) para extrair o SID de início de sessão da sandbox e, em seguida, CreateRestrictedToken(...) para construir o token restrito final.
  • Ainda dentro do runner, chama CreateProcessAsUserW(...) com esse token restrito para lançar o verdadeiro processo filho.
Diagrama que mostra o fluxo do executor de comandos para lançar comandos restritos.

A visão completa

Albert Einstein disse: «Tudo deve ser tornado tão simples quanto possível, mas não mais simples.» Nesse espírito, o nosso design resolveu adequadamente cada problema. A arquitetura final tem as quatro camadas que abordámos anteriormente:

  • o próprio codex.exe
  • codex-windows-sandbox-setup.exe para tratar de todo o trabalho de configuração elevado
  • codex-command-runner.exe para executar comandos de token restrito
  • O processo filho

Quando abordei este projeto pela primeira vez, não tinha uma noção clara de onde acabaria por chegar. A minha abordagem foi começar por instrumentar a capacidade de sandboxing no limite entre o Codex e o sistema operativo. Esta abordagem corresponde de perto à forma como a sandbox do Codex é implementada no macOS e no Linux.

À medida que fui aprendendo mais sobre as ferramentas específicas que o Windows disponibiliza, e depois de dezenas de decisões que equilibravam segurança e facilidade de utilização, o sistema cresceu até à forma atual — vários binários, utilizadores personalizados, regras de firewall, um passo de configuração elevado, processos assíncronos e muito mais.

Não é um sistema particularmente simples, mas cada elemento de complexidade foi acrescentado por necessidade, para criar uma sandbox que seja simultaneamente segura e, tanto quanto possível, não atrapalhe o utilizador.

Diagrama que mostra a arquitetura final da sandbox do Windows.

Equilibrar segurança com utilidade real

Ao trabalhar para proporcionar uma boa experiência aos utilizadores do Codex no Windows, o nosso objetivo era criar algo seguro que não comprometesse a utilidade — afinal, o objetivo de usar o Codex é permitir que agentes consigam trabalhar sem exigir a sua atenção constante.

Uma das maiores lições deste projeto foi que o Windows não nos ofereceu uma única primitiva que correspondesse de forma limpa a «agente de programação autónomo seguro». Combinámos várias ferramentas e conceitos para construir 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 uma parte do problema.

A outra lição foi que a segurança de um agente de programação é muito diferente da segurança de aplicações mais clássica. O Codex tem de funcionar para fluxos de trabalho reais de programadores. O trabalho de engenharia consistiu em equilibrar compatibilidade com cargas de trabalho agênticas e aplicação efetiva de controlos. Essa tensão moldou os compromissos do design final.

Tem curiosidade em ver a sandbox do Codex em ação? Experimente.