self signed certificate in certificate chain no se refiere a un certificado que hayas firmado tú. Quiere decir que la conexión HTTPS llegó firmada por una autoridad raíz que el programa no tiene en su almacén de confianza. En un portátil o una red de empresa, esa autoridad casi siempre es la CA raíz del proxy corporativo que inspecciona el tráfico.
La solución tiene tres pasos: consigue esa CA raíz en formato PEM, entrégasela al proceso que ha lanzado el error y reinícialo. Para el cliente propio de Codex, lo que cubre el inicio de sesión y las peticiones al modelo, basta con esto:
export CODEX_CA_CERTIFICATE="$HOME/certs/corp-root-ca.pem"
codex loginSi el error persiste, lo más probable es que lo esté lanzando otro proceso. La aplicación de escritorio, un servidor MCP escrito en Node o un curl que Codex ejecuta dentro de su sandbox no leen CODEX_CA_CERTIFICATE: cada uno tiene su propio ajuste.
Qué proceso lanza el error y qué ajuste lee cada uno
Localiza tu síntoma en la primera columna. El ajuste de la tercera solo sirve para el proceso de la segunda.
| Dónde ves el error | Proceso que no confía en la cadena | Ajuste que lee |
|---|---|---|
codex login, o una petición al modelo desde la CLI | Cliente propio de Codex | CODEX_CA_CERTIFICATE; si no existe, SSL_CERT_FILE |
| Servidor MCP remoto (HTTP) | Cliente propio de Codex | CODEX_CA_CERTIFICATE o SSL_CERT_FILE |
| Servidor MCP local (stdio) escrito en Node | El proceso Node del servidor | NODE_EXTRA_CA_CERTS o NODE_USE_SYSTEM_CA=1 |
Remote Control de la aplicación de escritorio en macOS, con SELF_SIGNED_CERT_IN_CHAIN en el registro | Capa Node de la aplicación | NODE_USE_SYSTEM_CA=1 al arrancar (testimonio de un usuario) |
curl: (60) SSL certificate problem en un comando que ejecutó Codex | La herramienta, dentro del sandbox | Un archivo de CA explícito: --cacert o CURL_CA_BUNDLE |
npm ERR! code SELF_SIGNED_CERT_IN_CHAIN | Node (npm) | NODE_EXTRA_CA_CERTS |
Las dos primeras filas proceden de la documentación de Codex y del cambio que amplió el soporte de CA personalizada; las de Node, de la documentación de Node.js. Las filas de la aplicación de escritorio y del sandbox se apoyan en issues abiertos por usuarios en el repositorio de Codex, que a 2 de octubre de 2026 no tienen respuesta de los mantenedores.
Qué significa self signed certificate in certificate chain en una red de empresa
El mensaje describe una cadena que termina en una raíz desconocida para el cliente. Es el error de verificación 19 de OpenSSL: el servidor presentó una cadena de certificados, la cadena acaba en una raíz autofirmada y esa raíz no está en el almacén de confianza del programa.
Todas las CA raíz son autofirmadas, también las públicas. Lo que cambia es si el programa las conoce. Cuando la empresa aplica inspección TLS, un proxy o un agente de seguridad descifra el tráfico y lo vuelve a firmar con la CA raíz de la organización. El navegador suele aceptarlo porque IT instaló esa raíz en el almacén del sistema, pero muchos programas de línea de comandos llevan su propia lista de raíces y no consultan la del sistema.
Hay otras causas con el mismo resultado: un antivirus que analiza HTTPS, o un servicio interno (una pasarela propia, un servidor MCP alojado en la empresa, una URL base personalizada) cuyo certificado emite una CA privada. El remedio es idéntico: darle al proceso la raíz correcta.

El error 18 de OpenSSL, self-signed certificate a secas, es otro caso: ahí es el propio certificado del servidor el que está autofirmado, no la raíz de una cadena.
Confirma quién firma la cadena con openssl s_client
Antes de tocar nada, mira qué emisor aparece al final de la cadena. Usa el host que figure en el error o en el registro; chatgpt.com sirve como ejemplo:
openssl s_client -connect chatgpt.com:443 -showcerts </dev/nullEn la salida, busca el bloque Certificate chain y lee la línea i: (issuer, emisor) del último certificado, como describe la documentación de s_client.
- Aparece el nombre de tu empresa o de un producto de seguridad. Hay inspección TLS y necesitas la CA raíz de esa organización.
- Aparece una autoridad pública conocida y la verificación termina bien. Ese host no está interceptado desde tu terminal. Repite la prueba con el host exacto del error: puede que el fallo esté en un servicio interno o en un servidor MCP, no en la conexión con OpenAI.
Los hosts que contacta Codex cambian según uses la CLI, la aplicación de escritorio o un servidor MCP, así que el del mensaje o el del registro es siempre mejor referencia que uno genérico.
Consigue la CA raíz en PEM: llavero, certmgr o IT
Necesitas el certificado raíz, no el del servidor ni uno intermedio, y en formato PEM: un archivo de texto que empieza por -----BEGIN CERTIFICATE-----.
En macOS, si IT ya instaló la raíz en el llavero del sistema, puedes exportarla desde Acceso a Llaveros o con el nombre que viste en el paso anterior:
mkdir -p "$HOME/certs"
security find-certificate -c "Nombre de la CA de tu empresa" -p \
/Library/Keychains/System.keychain > "$HOME/certs/corp-root-ca.pem"En Windows, abre certmgr.msc, ve a «Entidades de certificación raíz de confianza», localiza la CA de la empresa y expórtala como «X.509 codificado base 64 (.CER)». Ese archivo ya es PEM aunque la extensión sea .cer.
Si IT te entrega un archivo binario (DER), conviértelo:
openssl x509 -inform der -in corp-root-ca.cer -out "$HOME/certs/corp-root-ca.pem"Comprueba que tienes la raíz y que con ella la cadena valida:
openssl x509 -in "$HOME/certs/corp-root-ca.pem" -noout -subject -issuer
openssl s_client -connect chatgpt.com:443 \
-CAfile "$HOME/certs/corp-root-ca.pem" </dev/null 2>/dev/null | grep "Verify return code"En una raíz, subject e issuer coinciden. La segunda orden debe terminar en Verify return code: 0 (ok). Si devuelve otro código, el archivo no es la raíz que firma esa conexión, o la cadena tiene varias CA y hay que añadir las que faltan al mismo archivo, una detrás de otra.
Si no encuentras la raíz en tu equipo, pídesela a IT. Un PEM descargado de un sitio cualquiera o copiado de un foro no sirve: añadir una raíz equivale a confiar en todo lo que firme.
CLI de Codex: CODEX_CA_CERTIFICATE antes de codex login
El cliente propio de Codex lee CODEX_CA_CERTIFICATE y, si no está definida, SSL_CERT_FILE. La documentación de autenticación de Codex indica que, con un proxy TLS corporativo o una CA raíz privada, hay que apuntar la variable a un paquete PEM antes de iniciar sesión, y que el mismo ajuste vale para el inicio de sesión, las peticiones HTTPS normales y las conexiones WebSocket seguras.
En macOS y Linux:
export CODEX_CA_CERTIFICATE="$HOME/certs/corp-root-ca.pem"
codex loginEn Windows (PowerShell):
$env:CODEX_CA_CERTIFICATE = "C:\certs\corp-root-ca.pem"
codex loginPara que no se pierda al cerrar la terminal, añade el export a ~/.zshrc o ~/.bashrc, o crea la variable de entorno de usuario en Windows.
Según la descripción del cambio que extendió este soporte, fusionado el 13 de marzo de 2026, el orden es CODEX_CA_CERTIFICATE, luego SSL_CERT_FILE y, si no hay ninguna, las raíces del sistema. El paquete personalizado se carga junto con las raíces del sistema, no en su lugar, de modo que el archivo solo tiene que contener la CA de tu empresa. El mismo cambio cubre el cliente HTTP de los servidores MCP remotos y los WebSocket de respuestas y de tiempo real.
Tres comprobaciones si la variable parece no tener efecto:
- La ruta. Cuando el paquete no se puede cargar, el error nombra la variable y la ruta. Si lo ves, el archivo no existe, no es legible o no es PEM.
- El entorno del proceso. La variable tiene que estar en el entorno de quien arranca Codex. Un
exporten una terminal no llega a un IDE abierto desde el Dock o el menú de inicio; abre el IDE desde esa misma terminal o define la variable a nivel de usuario. - La versión. Las compilaciones anteriores a ese cambio solo confiaban en las raíces del sistema, y la documentación no dice qué versión lo incorporó. Actualiza Codex antes de buscar otra causa.
Tras un fallo de inicio de sesión, codex login deja un codex-login.log en el directorio de registros configurado; ahí aparece el host que rechazó la conexión.
Remote Control en la aplicación de escritorio: NODE_USE_SYSTEM_CA=1
En la aplicación de escritorio para macOS hay un caso documentado por un usuario en el que marcar la CA como de confianza en el llavero no basta. El issue #43489, abierto el 7 de septiembre de 2026 con la versión 26.901.51231 en macOS 26.6.1, describe que Remote Control falla con self signed certificate in certificate chain y el código SELF_SIGNED_CERT_IN_CHAIN en una red con inspección HTTPS, mientras curl, OpenSSL y un Node instalado aparte verifican bien. La línea del registro es:
[remote-control-transport] remote_control_websocket.connect_failed_before_openA quien lo reportó le funcionó arrancar la aplicación con la variable que hace que Node cargue el almacén del sistema:
NODE_USE_SYSTEM_CA=1 /Applications/ChatGPT.app/Contents/MacOS/ChatGPTEs el testimonio de una sola persona. A 2 de octubre de 2026 el issue sigue abierto sin respuesta de los mantenedores, y el comportamiento puede cambiar en versiones posteriores. La variable en sí es oficial: la documentación de Node.js explica que NODE_USE_SYSTEM_CA=1 carga el almacén de CA del sistema operativo (el llavero en macOS, el almacén de certificados en Windows, las ubicaciones por defecto de OpenSSL en Linux). No rebaja la verificación; solo amplía la lista de raíces a las que tu sistema ya admite.
En la documentación pública no consta si la capa Node de la aplicación lee CODEX_CA_CERTIFICATE, ni cómo se comporta la aplicación en Windows y Linux. Si allí ves el mismo error, prueba la misma variable al arrancar y, si no cambia nada, lleva el registro a IT o al issue.
Servidores MCP: los remotos usan el cliente de Codex, los de Node no
Un servidor MCP puede fallar por dos procesos distintos, y la forma de conectarlo decide cuál.
Servidor remoto por HTTP. La conexión la abre el cliente de Codex, así que vale CODEX_CA_CERTIFICATE. Si el servidor es interno y usa una CA privada distinta de la del proxy, añade las dos raíces al mismo archivo PEM.
Servidor local por stdio. Codex lanza un proceso aparte y es ese proceso el que sale a Internet. Si está escrito en Node (muchos se arrancan con npx), CODEX_CA_CERTIFICATE no le dice nada: Node lee NODE_EXTRA_CA_CERTS, que añade los certificados del archivo PEM a sus raíces integradas, o NODE_USE_SYSTEM_CA=1.
export NODE_EXTRA_CA_CERTS="$HOME/certs/corp-root-ca.pem"Dos detalles de la documentación de Node cambian el resultado. La variable se lee al arrancar el proceso, por lo que hay que reiniciar el servidor MCP, y en la práctica Codex, después de definirla. Y un archivo mal formado solo produce un aviso: el proceso arranca y el error TLS sigue ahí, sin indicar que el archivo se ignoró. Además, la variable debe estar en el entorno con el que se lanza el servidor, no solo en tu terminal.
curl: (60) dentro del sandbox de macOS: pasa un archivo de CA explícito
Si el error aparece en la salida de un comando que ejecutó Codex, como curl: (60) SSL certificate problem: self signed certificate in certificate chain, quien falla no es Codex, sino esa herramienta dentro del sandbox.
El issue #11182, abierto el 9 de febrero de 2026 con codex-cli 0.98.0, lo explica para macOS: las herramientas que usan el OpenSSL de Apple recurren al llavero para las raíces que no están en /etc/ssl/cert.pem, y el sandbox deniega esa consulta al servicio com.apple.TrustEvaluationAgent. El autor lo observó con --log-denials. El resultado es que el mismo curl funciona en tu terminal y falla cuando lo ejecuta Codex, aunque la CA esté en el llavero. El issue no recoge ninguna solución de los mantenedores.
Lo que sí puedes hacer es no depender del llavero: dale a la herramienta un archivo de CA explícito. Es comportamiento estándar de curl, no algo que el issue confirme para todos los casos:
curl --cacert "$HOME/certs/corp-root-ca.pem" https://servicio.interno.example/Para no repetirlo en cada comando, define la variable en el entorno que Codex pasa a los comandos que lanza. shell_environment_policy, en config.toml, controla qué variables reciben, y su tabla set asigna valores explícitos, según la documentación de configuración avanzada:
[shell_environment_policy]
set = { CURL_CA_BUNDLE = "/Users/tu-usuario/certs/corp-root-ca.pem", NODE_EXTRA_CA_CERTS = "/Users/tu-usuario/certs/corp-root-ca.pem" }Esa misma política es la razón de que una variable exportada en tu shell pueda no llegar a una herramienta: con inherit = "core" Codex pasa solo un conjunto recortado, y con inherit = "none", ninguna. Usa rutas absolutas y guarda el PEM en una ubicación que el sandbox pueda leer. El resto de permisos y opciones de red están en Sandbox de Codex y config.toml: permisos, aprobaciones y red.
Comprueba que el ajuste funciona y que no hay un archivo ignorado
La prueba válida es repetir la acción que falló, en un proceso nuevo y en la misma red.
| Proceso | Qué repetir | Resultado esperado |
|---|---|---|
| Cliente de Codex | codex login y una petición corta | El inicio de sesión termina y llega la respuesta, sin error de carga de CA |
| Proceso Node | Reiniciar el servidor MCP o la aplicación | Desaparece SELF_SIGNED_CERT_IN_CHAIN y no hay aviso sobre el archivo de NODE_EXTRA_CA_CERTS |
| Comando en el sandbox | Pedir a Codex que repita el mismo curl | Respuesta HTTP en lugar de curl: (60) |
Si el mensaje cambia en vez de desaparecer, ya no es el mismo problema. Un tiempo de espera o un rechazo de autenticación apuntan al proxy, no a la confianza en el certificado.

Por qué NODE_TLS_REJECT_UNAUTHORIZED=0 no es la solución y cuándo acudir a IT
Desactivar la verificación hace desaparecer el mensaje y también la protección. La documentación de Node.js advierte de que NODE_TLS_REJECT_UNAUTHORIZED=0 desactiva la validación de certificados y deja las conexiones TLS expuestas a ataques de intermediario. Lo mismo vale para strict-ssl false en npm o curl -k: el proceso aceptaría cualquier certificado, y por esa conexión viajan tus credenciales de Codex y tu código.
Añadir la CA raíz de la empresa es lo contrario: la verificación sigue activa y solo se amplía la lista de autoridades admitidas con una que tu organización ya usa en todos sus equipos.
Deja de probar por tu cuenta y acude a IT cuando:
- no encuentras la CA raíz en el equipo o no sabes cuál de varias es la que firma;
openssl s_clientcon-CAfileno devuelveVerify return code: 0 (ok)con el archivo que te dieron;- el emisor que ves no pertenece a tu empresa ni a un producto de seguridad que reconozcas;
- la variable correcta está cargada, el proceso se ha reiniciado y el error sigue igual.
Lleva la salida de openssl s_client, el host que falla y el proceso que lanza el error. Con eso IT puede darte el paquete de CA correcto o revisar si ese destino debe quedar fuera de la inspección, una decisión que corresponde a ellos.
Preguntas frecuentes sobre el error de certificado en Codex
¿El inicio de sesión con código de dispositivo evita el error?
No. codex login --device-auth está pensado para equipos sin navegador o redes que bloquean la redirección de vuelta a tu propio equipo, pero sigue haciendo peticiones HTTPS a través del mismo proxy. Define CODEX_CA_CERTIFICATE igual que con el inicio de sesión normal. Es una función beta que hay que activar en los ajustes de seguridad de ChatGPT.
¿Por qué en mi caso aparece «Token exchange failed» y no «self signed»?
Puede ser la misma causa con otro mensaje. Un issue de noviembre de 2025, con la CLI 0.58.0 detrás de un proxy corporativo con CA propia, recoge Token exchange failed: error sending request for url (https://auth.openai.com/oauth/token ). Es anterior al soporte de CA personalizada en todo el cliente. Actualiza Codex y define la variable; si el fallo continúa, las demás causas de ese mensaje están separadas por fases en Codex Token Exchange Failed: identifica la fase antes de repetir el login.
¿Sirve copiar auth.json desde otro equipo para saltarse el login?
Evita el paso de inicio de sesión, pero no el problema: las peticiones posteriores pasan por el mismo proxy y fallan igual sin la CA. Además, la documentación pide tratar ese archivo, que Codex guarda en la carpeta .codex de tu usuario, como una contraseña.
¿Por qué el navegador funciona y Codex no en la misma red?
El navegador usa el almacén de confianza del sistema, donde IT instaló la raíz. El cliente de Codex añade a esas raíces el paquete que indiques, Node usa su lista integrada salvo que definas una de sus dos variables, y las herramientas dentro del sandbox de macOS pueden no alcanzar el llavero. Son listas distintas en el mismo equipo.
¿El error a mitad de tarea tiene la misma causa?
Si el texto es el mismo, sí: alguna conexión de esa tarea pasa por un proceso sin la raíz. Si lo que ves es una reconexión sin mención al certificado, el recorrido es otro y está en Codex se queda en Reconnecting: cómo recuperar la tarea sin borrar sesiones.



