Pasar al contenido principal
OpenAI

13 de mayo de 2026

IngenieríaSeguridad

Crear un sandbox seguro y eficaz para habilitar Codex en Windows

Por David Wiesen, miembro del personal técnico

Cargando...

Cuando me uní al equipo de ingeniería de Codex en septiembre de 2025, Codex para Windows no tenía una implementación de sandbox, por lo que los usuarios de Windows se veían obligados a elegir entre dos opciones deficientes al usar los agentes de codificación de OpenAI:

  1. Aprobar casi todos los comandos (incluso las lecturas) que un agente de codificación quisiera ejecutar, lo que es ineficiente y molesto. Una gran ventaja de usar Codex es que no tienes que hacer todo el trabajo tedioso por tu cuenta.
  2. Habilitar el modo de acceso total: dejar que Codex ejecute todos los comandos sin aprobación ni restricciones, lo que elimina la fricción a costa de la supervisión.

Codex, nuestro agente de codificación, se ejecuta en las computadoras portátiles de los desarrolladores, ya sea a través de la CLI, la extensión del IDE o la aplicación de escritorio. Gestiona una conversación entre una persona frente a un teclado y un modelo que se ejecuta en la nube para manejar la inferencia.

Codex se ejecuta con los permisos de un usuario real de forma predeterminada, lo que significa que puede hacer todo lo que el usuario puede hacer. Esto es potente y potencialmente peligroso. El modelo de codificación puede indicarle al motor que ejecute comandos de forma local, desde ejecutar pruebas hasta leer o editar un archivo o crear una rama de Git, por lo que el modo predeterminado de Codex intenta encontrar el equilibrio adecuado entre eficacia y seguridad. Este modo predeterminado permite que Codex lea archivos casi en cualquier lugar y escriba archivos dentro de tu espacio de trabajo (es decir, el directorio donde ejecutas Codex), sin acceso a internet a menos que especifiques que lo quieres. Para lograr esta restricción automática de escribir archivos y acceder a la red dentro de límites seguros, Codex necesita un sandbox que realmente imponga estas restricciones.

Un sandbox es un entorno de ejecución restringido. Cuando un desarrollador usa Codex, el sistema operativo de su computadora inicia un comando con permisos reducidos, y esas restricciones se propagan por todo el árbol de procesos. Cada comando de Codex se ejecuta en un entorno aislado desde el inicio, y cada proceso descendiente permanece dentro del mismo límite.

Diagrama que muestra los límites de aislamiento del sistema operativo del sandbox de Codex.

Codex necesita funciones de aislamiento impuestas por el sistema operativo de la computadora para implementar un sandbox eficaz. Algunos sistemas operativos ofrecen utilidades que hacen esto bien (p. ej., Seatbelt en macOS, seccomp o bubblewrap en Linux); sin embargo, Windows actualmente no ofrece este tipo de capacidad de forma nativa.

Para hacer que Codex sea tan seguro y fácil de usar en Windows como ya lo es en cualquier otro lugar, necesitábamos implementar nuestro propio sandbox.

Donde las herramientas existentes de Windows no fueron suficientes

Windows ofrece algunas herramientas y primitivas para el aislamiento. Aunque ninguna cumplía del todo con nuestros requisitos, analizamos varias soluciones potenciales, concretamente AppContainer, Espacio aislado de Windows y el etiquetado de Control de integridad obligatorio.

AppContainer

  • Qué: AppContainer es el sandbox nativo de Windows, un modelo de aislamiento basado en capacidades creado para aplicaciones que saben, de antemano, exactamente a qué necesitan acceder.
  • Por qué: resultaba atractivo porque ofrece un límite real del sistema operativo en lugar de restricciones de mejor esfuerzo.
  • Por qué no: Codex no es una aplicación con un alcance estrictamente delimitado. Impulsa flujos de trabajo de desarrollo abiertos: shells, Git, Python, administradores de paquetes, herramientas de compilación y cualquier otro binario que el agente decida que necesita. En la práctica, eso hizo que AppContainer no encajara con el problema. Era un aislamiento sólido, pero para una clase de cargas de trabajo mucho más limitada que la de permitir que un agente opere como un desarrollador.

Espacio aislado de Windows

  • Qué: Espacio aislado de Windows es la máquina virtual ligera y descartable de Microsoft. Obtienes un escritorio de Windows nuevo con un límite de aislamiento sólido y cualquier cosa que hagas dentro desaparece cuando termina la sesión.
  • Por qué: era interesante por motivos evidentes: es mucho más compatible con software arbitrario que AppContainer y, desde una perspectiva de seguridad, ofrece un aislamiento mucho más sólido.
  • Por qué no: Codex necesita actuar directamente sobre los archivos, las herramientas y el entorno reales del usuario, no dentro de un escritorio desechable y separado que requeriría configuración y puente entre host e invitado. También tenía un problema fundamental de producto: Espacio aislado de Windows ni siquiera está disponible en las ediciones Home de Windows.

Etiquetado de Control de integridad obligatorio (MIC)

  • Qué: Windows tiene un concepto llamado niveles de integridad, como bajo, medio y alto, que determinan cuánto confía el sistema en objetos y procesos. La regla básica es que un proceso de menor integridad no puede escribir en un objeto con un nivel de integridad superior, incluso si la ACL estándar lo permitiera de otro modo. Por ejemplo, un proceso de baja integridad se considera menos confiable, por lo que Windows le impide escribir en objetos normales de integridad media, a menos que esos objetos se reetiqueten explícitamente para permitirlo.
  • Por qué: MIC se veía atractivo en teoría: ejecutar Codex con integridad baja, volver a etiquetar las raíces grabables como de integridad baja y dejar que Windows impusiera la prohibición de escritura en cualquier otro lugar. Eso nos habría dado una vía que no requiere privilegios de administrador, respaldada por un mecanismo real del sistema operativo.
  • Por qué no: al igual que las ACL, las etiquetas de integridad modifican el sistema de archivos real del host y, en este caso, el cambio semántico es especialmente amplio. Marcar un espacio de trabajo como de baja integridad no significa simplemente que Codex puede escribir aquí. Significa que los procesos de baja integridad en general pueden escribir allí. En una máquina de desarrollador real, eso convierte la copia de trabajo real del usuario en un sumidero de baja integridad para el host, lo que es mucho más riesgoso que conceder ACL cuidadosamente delimitadas a un diseño específico de aislamiento. Incluso si las herramientas de desarrollo de integridad media siguen funcionando, el modelo de confianza subyacente del espacio de trabajo cambió de una manera difícil de contener y aún más difícil de justificar.

Después de evaluar todas las opciones y ver que ninguna servía como punto de partida, comenzamos a diseñar nuestra propia solución para ofrecer una buena experiencia de Codex a los usuarios de Windows.

El primer prototipo: el sandbox no elevado

Nuestro primer prototipo funcional usó una combinación de conceptos y herramientas de Windows para implementar el sandbox que necesitábamos. Desde el principio, uno de los objetivos fue hacer que esto funcionara sin requerir elevación, lo que significa que Codex no tendría que solicitar al usuario privilegios de administrador solo para configurar o ejecutar el sandbox. Eso implicaba determinar cómo establecer límites razonables para dos cosas: las operaciones de escritura en archivos y el acceso a la red.

Limitar las escrituras de archivos

Si no limitábamos en absoluto las escrituras de archivos, tendríamos un problema de seguridad. Si las limitábamos demasiado, el sandbox perjudicaría la productividad del usuario al necesitar aprobación constante. Para resolver este problema, nos apoyamos en dos bloques fundamentales importantes de Windows: los SID y los tokens con restricción de escritura.

Los SID nos permiten dar al sandbox una identidad

Un SID, o identificador de seguridad, es la identidad que Windows asocia con los permisos. Cada usuario tiene un SID, los grupos tienen SIDs e incluso una sola sesión de inicio de sesión recibe su propio SID. Por ejemplo, una sesión iniciada actualmente podría tener un SID como S-1-5-5-X-Y. El SID asignado al grupo de administradores locales podría ser S-1-5-32-544.

Windows también te permite crear SID sintéticos que no corresponden a un usuario real, pero que aun así pueden aparecer en las ACL (listas de control de acceso), que definen quién puede leer, escribir o ejecutar archivos o directorios específicos. Eso hace que los SID sean una primitiva útil para nuestro sandbox: podemos crear SID exclusivamente para que los use el sandbox de Codex, sin interferir con nada más en la máquina.

Los tokens con restricción de escritura limitan dónde Codex puede modificar archivos

Los tokens de proceso son objetos de seguridad en Windows que definen la identidad y los privilegios de un proceso en ejecución. Determinan qué acciones puede realizar un proceso. Un token con restricción de escritura es un tipo particular de token de proceso que hace que Windows realice una comprobación de acceso adicional en las operaciones de escritura.

Para que una escritura tenga éxito, deben aprobarse dos verificaciones:

  1. La identidad normal del usuario (el propietario del token) debe tener permiso para hacerlo
  2. Al menos un SID de la lista de SID restringidos del token también debe tener acceso concedido
Diagrama titulado El acceso de escritura del sandbox requiere tanto acceso de usuario normal como acceso SID sandbox-write.

En la práctica, estas verificaciones nos permitieron usar ACL para definir exactamente dónde el sandbox podía modificar el sistema de archivos, lo que nos ofrecía la granularidad que necesitábamos en torno a las operaciones de escritura.

Con SID y tokens con restricción de escritura, nuestro sandbox no elevado funcionaba así:

  1. La configuración del sandbox creaba un SID sintético llamado sandbox-write.
  2. Se concedía al SID sandbox-write acceso de escritura, ejecución y eliminación a lo siguiente:
    1. El directorio de trabajo actual.
    2. Cualquier writable_roots adicional configurado en config.toml.
  3. La configuración del sandbox denegaba explícitamente a ese mismo SID el acceso de escritura a ubicaciones de solo lectura dentro de áreas escribibles como:
    1. <cwd>/.git
    2. <cwd>/.codex
    3. <cwd>/.agents
  4. Codex iniciaba comandos bajo un token con restricción de escritura cuya lista de SID restringidos incluye Everyone, el SID de la sesión actual iniciada y el SID sintético sandbox-write.

Este flujo resolvía de forma eficaz la limitación de escrituras de archivos y parecía prometedor. Ahora necesitábamos una solución para limitar el acceso a la red del sandbox.

Limitar el acceso a la red

Limitar el acceso a la red es una parte importante del sandbox; sin ello, el código malicioso podría exfiltrar datos de la máquina hacia internet. Como queríamos evitar el requisito de elevación, teníamos opciones limitadas para bloquear con efectividad el tráfico de red. Las herramientas que queríamos usar, como Firewall de Windows, en general no podían instalarse sin permisos de administrador.

Sin Firewall de Windows como opción, limitamos lo que podíamos controlar. Intentamos hacer que el entorno secundario fallara de forma cerrada para los tipos de herramientas con acceso a la red que los desarrolladores realmente usan, de modo que los comandos de Git, los instaladores de paquetes, etc., fallaran en el sandbox y el usuario tuviera que aprobar cualquier operación con exposición a internet. La idea era inutilizar las rutas de escape obvias: enviar el tráfico compatible con proxy a un punto de acceso inactivo, hacer que el transporte HTTP(S) de Git hiciera lo mismo y lograr que Git sobre SSH fallara de inmediato. Además de eso, antepusimos un pequeño directorio denybin al PATH y reordenamos PATHEXT para que los scripts stub de SSH y SCP se resolvieran antes que los binarios reales.

Por ejemplo, aquí están algunas de las anulaciones específicas del entorno que usamos para limitar el acceso a la red:

  • 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 muestra la arquitectura del sandbox elevado con reglas de firewall y un usuario dedicado de Windows.

Eso capturaba mucho del tráfico normal impulsado por herramientas, pero seguía siendo solo indicativo. Un proceso podía ignorar el entorno, evitar PATH o simplemente abrir sockets de forma directa: demasiado riesgoso.

El enfoque no elevado implicaba concesiones

Como ocurre con cualquier implementación de software interesante, el primer prototipo tenía algunas ventajas y desventajas. Aunque cumplía su función con solo unas pocas capacidades estándar de Windows, permitía escrituras del sistema de archivos muy explícitas y granulares, y se ejecutaba sin privilegios elevados —lo que reducía la necesidad de que los usuarios aceptaran prompts de elevación excesivos o fueran administradores en su máquina local—, tenía algunas desventajas importantes, algunas de las cuales lo descartaron como nuestro diseño final:

  • Velocidad de configuración: aplicar las ACL del espacio de trabajo puede ser costoso según la topología del directorio del espacio de trabajo.
  • Huella: aplicábamos ACL reales al sistema del desarrollador, aunque la huella no era particularmente invasiva porque todas las ACL aplicadas corresponden a un SID sintético creado a medida que solo usa el sandbox.
  • Semántica difícil de cambiar: la dependencia de las ACLs para las restricciones basadas en archivos significa que cambiar la semántica del sandbox es costoso y complejo. Mientras que en macOS podemos cambiar dinámicamente la forma en que generamos el archivo .sbpl utilizado para configurar Seatbelt, el sandbox de Windows podría requerir una operación lenta e intensa para ajustar las ACL.
  • La protección de red es débil. Como se mencionó antes, era indicativa, algunos programas que implementaban su propia pila de red sin duda la eludirían y no estaba diseñada para resistir código adversarial.

Los primeros tres problemas son inherentes a una implementación de sandbox personalizada lo bastante flexible para flujos con agentes. Sin embargo, la historia de la supresión de red era distinta.

La supresión de red es demasiado importante

Además de que un agente malicioso pudiera eludir fácilmente la supresión de red basada en el entorno, mucho código o binarios bien intencionados también la eludirían simplemente si no respetaban las variables proxy del entorno o si implementaban su propio código de red basado en sockets. Sentimos que este aspecto bastaba para considerar invertir en un mejor modo de sandbox.

Para obtener una mejor supresión de red, queríamos usar Firewall de Windows, que nos permite bloquear el tráfico de red saliente para usuarios o programas. Lamentablemente, no podíamos crear de forma efectiva una regla de firewall que se aplicara solo a los comandos generados por el ejecutor de Codex por algunas razones:

  • Windows no permite hacer coincidir una regla de firewall con la identidad no principal de un token restringido. Esto significa que no podíamos aplicar una regla de firewall a cualquier token que incluya nuestro SID sintético en su lista de SID restringidos.
  • Aunque podríamos crear una regla de firewall que coincida con un binario específico, eso solo nos permite limitar la conectividad de red para codex.exe en sí. No se aplicaría a los procesos que el agente inicia en nombre del usuario, como los procesos de Git o Python.
  • Otras dimensiones de coincidencia del firewall también tenían una estructura incorrecta. Las reglas de ámbito de usuario seguían coincidiendo con el usuario real de Windows en el diseño sin elevación de privilegios, no solo con el secundario restringido. Las reglas basadas en la ruta del programa eran demasiado generales: podían bloquear codex.exe o python.exe en general, pero no esta invocación de python.exe en un entorno aislado. Las reglas basadas en puertos o direcciones también eran una política equivocada por completo. Por ejemplo, no queríamos bloquear el puerto 443; queríamos bloquear el acceso saliente arbitrario para este árbol de procesos restringido específico.

Para aplicar una regla de firewall específicamente a nuestros comandos en un entorno aislado, necesitábamos ejecutarlos como un principal separado, no como el usuario real. Este enfoque nos llevó por un camino nuevo, en el que relajamos nuestra restricción de sin elevación.

El rediseño: el sandbox elevado

La próxima iteración del sandbox, que es nuestra implementación actual, requiere permisos de administrador elevados durante la configuración. Por lo tanto, lo denomino "el sandbox elevado". En el límite donde Codex lanza un comando en el sistema, el sandbox con privilegios elevados parece igual que el entorno sin privilegios elevados. Sigue ejecutando procesos secundarios bajo un token restringido —de manera similar, un token write_restricted con la misma lista de SID restringidos de [Everyone, Logon, Synthetic]—; sin embargo, la entidad principal de este token ya no es el usuario real de Windows, sino uno de los dos usuarios locales creados por el propio Codex:

  • CodexSandboxOffline (el que está sujeto a reglas de firewall)
  • CodexSandboxOnline (el que no está sujeto a reglas de firewall)

Este detalle, aparentemente pequeño, en realidad tiene grandes implicaciones para el sandbox, quién puede usarlo y la complejidad de su configuración y ejecución en tiempo de ejecución.

Diagrama que muestra las anulaciones del entorno de red para el sandbox no elevado.

Visualmente es similar al prototipo no elevado, con la introducción de reglas de firewall y un usuario de Windows dedicado, que es quien realmente ejecuta los comandos. (Sin embargo, la introducción de estos nuevos conceptos significa que hay más trabajo de configuración que hacer antes de que el sandbox pueda comenzar a ejecutar y proteger comandos).

Ahora necesitamos un paso de configuración inicial

El diseño del sandbox no elevado tenía un paso de configuración simple, pero era relativamente pequeño:

  • Crear un SID sintético si hace falta.
  • Aplicar ACL para el SID sintético sandbox-write.

El sandbox elevado, en cambio, tiene más que hacer.

  • Crear un SID sintético, si todavía no se creó.
  • Crear los usuarios online y offline del sandbox, si todavía no se crearon.
  • Almacenar localmente las credenciales de los usuarios recién creados y cifrarlas con la API de protección de datos (DPAPI) de Windows en un lugar donde los usuarios del sandbox no puedan leer realmente.
  • Crear reglas de firewall que bloqueen todo el acceso saliente a la red para el usuario CodexSandboxOffline o, si ya existen, validar que sean correctas.

Hay una complicación adicional en la etapa de configuración. Se espera que el sandbox de Codex tenga acceso de lectura equivalente al del usuario real de Windows. Esto se logró en el sandbox sin privilegios elevados, donde el SID principal del token restringido era el usuario de Windows. Sin embargo, eso conlleva un costo cuando la entidad principal se convierte en un nuevo usuario de CodexSandbox. Muchos directorios relevantes en Windows otorgarán permisos de lectura/ejecución a Usuarios autenticados. Un ejemplo notable es el directorio de perfil del usuario. De forma predeterminada, los usuarios de Windows no pueden leer los directorios de perfil de otros usuarios de Windows, por lo que incluso las lecturas simples de archivos fallarían en muchos escenarios.

Para solucionar esto, agregamos otra capa al proceso de configuración del sandbox: una para conceder ACL de lectura a los usuarios del sandbox donde esas ACL quizá no existieran todavía. Por ejemplo, a algunos directorios de Windows de uso común:

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

Como esta lista de directorios es de mejor esfuerzo y la instalación de ACL en cada uno puede ser bastante costosa, ejecutamos esta lógica de forma asíncrona para que el paso de configuración del sandbox, que sí bloquea a los usuarios, no tenga que esperar a que se complete.

Encapsulamos la lógica de configuración en su propio binario, en parte para cruzar el límite de UAC solo cuando fuera necesario. Pero la razón de fondo era arquitectónica: la configuración del entorno de pruebas cumple una función fundamentalmente distinta a la de codex.exe. Mantener la lógica de configuración del entorno de pruebas en un binario dedicado permitió que codex.exe siguiera siendo un ejecutor normal, sin elevación; evitó que la maquinaria de configuración exclusiva de Windows inflara codex.exe en otras plataformas; desacopló el trabajo de configuración de mayor duración de la vida del proceso principal y nos dio un lugar para manejar las diferentes rutas de configuración que el entorno de pruebas necesitaba.

Diagrama que muestra el paso de configuración inicial del sandbox elevado.

El ejecutor de comandos es un nuevo binario que realmente ejecuta los comandos del usuario

Debido a cómo funcionan en Windows los límites de inicio de sesión de usuarios y tokens, no podíamos seguir creando un token restringido y generando un proceso bajo él como podíamos con el sandbox no elevado. Para realmente generar comandos como un usuario diferente de Windows, nuestra primera idea fue el siguiente flujo:

  • codex.exe se ejecuta como el usuario real de Windows. Luego, en una secuencia, Codex:
    • Llama a LogonUserW(...) para el usuario del sandbox.
    • Llama a CreateRestrictedToken(...) en ese token de usuario de sandbox.
    • Mediante ese token restringido de usuario de sandbox, llama a CreateProcessAsUserW(...) para iniciar el proceso secundario final.

En la práctica, ese flujo deseado no funcionó debido a una barrera de privilegios en CreateProcessAsUserW(...). Esto significa que codex.exe podía crear un token restringido para el usuario del entorno aislado, pero no podía iniciar de forma confiable un proceso secundario con ese token desde el lado del usuario real del límite. Necesitábamos un proceso que ya se estuviera ejecutando como el usuario del entorno aislado; esto permitiría que el paso de restricción y la creación final ocurrieran del lado del usuario del entorno aislado del límite, en lugar de hacerlo del lado del usuario real.

Ese requisito dio lugar a codex-command-runner.exe, un nuevo binario cuya única función es emitir un token restringido e iniciar el comando solicitado. En lugar de pedirle a codex.exe que hiciera por sí mismo todo el flujo (usuario real → usuario del sandbox → token restringido → proceso hijo), dividimos el flujo en dos:

Parte 1

  • codex.exe llama a CreateProcessWithLogonW(...) para iniciar codex-command-runner.exe como el usuario del sandbox, sin usar todavía un token restringido.

Parte 2

  • Dentro del ejecutor, OpenProcessToken(GetCurrentProcess(), ...) abre el propio token del ejecutor, que ya pertenece al usuario del sandbox.
  • El ejecutor llama a GetTokenInformation(...) para extraer el SID de inicio de sesión del sandbox y luego a CreateRestrictedToken(...) para construir el token restringido final.
  • Todavía dentro del ejecutor, llama a CreateProcessAsUserW(...) con ese token restringido para iniciar el proceso hijo real.
Diagrama que muestra el flujo del ejecutor de comandos para iniciar comandos restringidos.

La visión completa

Albert Einstein dijo: "Todo debe hacerse tan simple como sea posible, pero no más". Con ese espíritu, nuestro diseño resolvió adecuadamente cada problema. La arquitectura final tiene las cuatro capas que ya cubrimos antes:

  • codex.exe en sí.
  • codex-windows-sandbox-setup.exe para encargarse de todo el trabajo de configuración relacionado con la elevación.
  • codex-command-runner.exe para ejecutar comandos con token restringido.
  • El proceso hijo.

Cuando abordé este proyecto por primera vez, no tenía una idea clara de a dónde terminaría llegando. Mi enfoque fue empezar instrumentando la capacidad de sandboxing en el límite entre Codex y el sistema operativo. Este enfoque coincide de cerca con cómo se implementa el sandbox de Codex en macOS y Linux.

A medida que aprendí más sobre las herramientas específicas que ofrece Windows, y a través de decenas de decisiones que equilibraban seguridad y facilidad de uso, el sistema creció hasta tomar su forma actual: múltiples binarios, usuarios personalizados, reglas de firewall, un paso de configuración con elevación, procesos asíncronos y más.

No es un sistema particularmente simple, pero cada pieza de complejidad se añadió por necesidad, para construir un sandbox que sea tanto seguro como, en la medida de lo posible, que no se interponga en el camino del usuario.

Diagrama que muestra la arquitectura final del sandbox de Windows.

Equilibrar la seguridad con la utilidad real

Al trabajar para ofrecer una buena experiencia de usuario a los usuarios de Codex en Windows, nuestro objetivo fue crear algo seguro que no comprometiera la utilidad; el objetivo completo de usar Codex es que los agentes puedan hacer trabajo sin tu atención constante.

Una de las lecciones más importantes de este proyecto fue que Windows no nos entregó una sola primitiva que se correspondiera limpiamente con un agente de codificación autónomo seguro. Combinamos varias herramientas y conceptos para construir algo coherente. Algunas ideas iniciales fueron callejones sin salida. El diseño final fue un híbrido de prototipos anteriores, cada uno resolviendo una parte del problema.

La otra lección fue que la seguridad para un agente de codificación es una especie distinta de la seguridad de aplicaciones más clásica. Codex tiene que funcionar para flujos de trabajo reales de desarrolladores. El trabajo de ingeniería consistió en equilibrar la compatibilidad con cargas de trabajo con agentes frente a una imposición real. Esa tensión dio forma a las concesiones del diseño final.

¿Tienes curiosidad por ver el sandbox de Codex en acción? Pruébalo.