# Codex: как исправить self signed certificate in certificate chain

> Ошибка значит, что процесс не доверяет корневому сертификату корпоративного прокси. Получите его в PEM и передайте настройке, которую читает упавший процесс.

- Source: https://www.aifreeapi.com/ru/posts/codex-self-signed-certificate-in-certificate-chain
- Language: ru
- Published: 2026-10-02
- Updated: 2026-10-02
- Publisher: AI Free API (https://www.aifreeapi.com)

Сообщение `self signed certificate in certificate chain` в Codex почти никогда не означает, что вы сами что-то подписали. Оно говорит о сети: цепочка сертификатов, которую получил процесс, заканчивается корневым сертификатом, которого нет в его хранилище доверенных. На рабочем ноутбуке это обычно корневой сертификат корпоративного прокси, который проверяет HTTPS-трафик и переподписывает его сертификатом компании.

Исправление состоит из двух действий: получить этот корневой сертификат в формате PEM и передать его той настройке, которую читает именно упавший процесс. Для Codex CLI это выглядит так:

```bash
export CODEX_CA_CERTIFICATE="$HOME/certs/corp-root-ca.pem"
codex login
```

Если ошибка появилась не в самом Codex, а в настольном приложении, MCP-сервере или в команде, которую Codex запустил в песочнице, эта переменная может не помочь: у каждого из этих процессов свой источник доверия. Отключать проверку сертификатов (`NODE_TLS_REJECT_UNAUTHORIZED=0`, `curl -k`) не нужно ни в одном из случаев.

## Какой процесс выдал ошибку и какую настройку он читает

Сначала найдите, где именно вы увидели текст ошибки: от этого зависит, какая настройка её уберёт.

| Где появилась ошибка | Какой процесс не доверяет цепочке | Что настроить |
| --- | --- | --- |
| `codex login`, запросы и WebSocket в Codex CLI | Собственный клиент Codex | `CODEX_CA_CERTIFICATE`, если её нет — `SSL_CERT_FILE` |
| MCP-сервер, подключённый по `url` | HTTP-клиент MCP внутри Codex | Те же `CODEX_CA_CERTIFICATE` / `SSL_CERT_FILE` |
| MCP-сервер, запущенный через `command` (`npx`, `node`) | Отдельный процесс Node | `NODE_EXTRA_CA_CERTS` в окружении этого сервера |
| Remote Control в настольном приложении, в журнале `SELF_SIGNED_CERT_IN_CHAIN` | Node-слой приложения | По сообщению пользователя на macOS — запуск с `NODE_USE_SYSTEM_CA=1` |
| `curl: (60) SSL certificate problem: self signed certificate in certificate chain` в команде, которую выполнил Codex | curl внутри песочницы | Явный файл: `CURL_CA_BUNDLE` или `--cacert` |
| `npm install` и другие Node-инструменты, запущенные Codex | Процесс Node внутри песочницы | `NODE_EXTRA_CA_CERTS`, переданная через политику окружения |

![Четыре карточки: Codex CLI и MCP по url читают CODEX_CA_CERTIFICATE, MCP-сервер через command — NODE_EXTRA_CA_CERTS, настольное приложение — NODE_USE_SYSTEM_CA=1, команды в песочнице — CURL_CA_BUNDLE](https://www.aifreeapi.com/posts/ru/codex-self-signed-certificate-in-certificate-chain/img/process-trust-map.webp)

Первые две строки опираются на документацию и код Codex, третья и шестая — на документацию Node.js. Четвёртая и пятая описаны только в открытых обращениях пользователей в репозитории `openai/codex`, сопровождающие их не подтверждали; подробности — в соответствующих разделах ниже.

## Что означает self signed certificate in certificate chain

Это ошибка проверки цепочки с кодом 19 в OpenSSL: сервер предъявил цепочку, которая упирается в самоподписанный корневой сертификат, а клиент этого корневого сертификата не знает. Самоподписан любой корневой сертификат, в том числе публичных удостоверяющих центров; разница в том, что публичные заранее лежат в хранилище доверенных, а корпоративный — нет.

В корпоративной сети причина чаще всего одна: прокси или агент безопасности выполняет инспекцию HTTPS. Он принимает соединение с `chatgpt.com` или `api.openai.com`, проверяет содержимое и отдаёт вашему компьютеру тот же ответ, но с сертификатом, выпущенным корневым CA организации. Браузер при этом работает, потому что ИТ-служба добавила корневой сертификат в системное хранилище. Процесс, который системное хранилище не читает, видит незнакомый корневой сертификат и прерывает соединение.

Реже встречаются другие причины: антивирус с проверкой HTTPS, собственный шлюз или MCP-сервер с сертификатом частного CA, нестандартный базовый URL. Похожее сообщение `self-signed certificate` без слов про цепочку (код 18) — другой случай: самоподписан сам сертификат сервера, а не корень цепочки.

## Кто переподписал соединение: проверка через openssl s_client

Прежде чем что-либо менять, посмотрите, чья подпись стоит в конце цепочки. Подставьте хост из текста ошибки или журнала; если его нет, начните с `chatgpt.com`:

```bash
openssl s_client -connect chatgpt.com:443 -showcerts </dev/null
```

В выводе найдите блок `Certificate chain`. Каждая запись состоит из строки `s:` (кому выдан сертификат) и `i:` (кем выдан). Смотрите на `i:` последней записи:

- название вашей компании или продукта безопасности — инспекция HTTPS подтверждена, нужен корневой сертификат именно этого издателя;
- публичный удостоверяющий центр — трафик к этому хосту не переподписывается, причину ищите в другом хосте из ошибки или в самом процессе;
- незнакомое название, которое не относится ни к компании, ни к известным вам средствам защиты, — не добавляйте его в доверенные, покажите вывод ИТ-службе.

Если выход в интернет возможен только через явный прокси, добавьте к команде `-proxy хост:порт`. Описание параметров — в [документации OpenSSL по `s_client`](https://docs.openssl.org/master/man1/openssl-s_client/).

### Как получить корневой сертификат в формате PEM

Самый надёжный источник — ИТ-служба: попросите корневой сертификат корпоративного прокси файлом PEM. Если он уже установлен в системе, его можно выгрузить самостоятельно:

- macOS: «Связка ключей» → связка «Система» → найдите сертификат с именем из строки `i:` → «Файл» → «Экспортировать объекты», формат `.pem`;
- Windows: `certmgr.msc` → «Доверенные корневые центры сертификации» → «Сертификаты» → «Экспорт», формат «X.509 в кодировке Base-64».

Файл PEM — текстовый, начинается со строки `-----BEGIN CERTIFICATE-----`. Убедитесь, что в нём тот самый издатель:

```bash
openssl x509 -in "$HOME/certs/corp-root-ca.pem" -noout -subject -issuer -enddate
```

У корневого сертификата `subject` и `issuer` совпадают, и это имя должно совпасть с `i:` последней записи из предыдущего шага.

## Codex CLI: CODEX_CA_CERTIFICATE и SSL_CERT_FILE

Клиенту Codex достаточно пути к PEM-файлу в переменной окружения. В [документации по аутентификации](https://learn.chatgpt.com/docs/auth) сказано: если сеть использует корпоративный TLS-прокси или частный корневой CA, задайте `CODEX_CA_CERTIFICATE` до входа; когда она не задана, Codex использует `SSL_CERT_FILE`.

macOS и Linux:

```bash
export CODEX_CA_CERTIFICATE="$HOME/certs/corp-root-ca.pem"
codex login
```

Windows PowerShell:

```powershell
$env:CODEX_CA_CERTIFICATE = "C:\certs\corp-root-ca.pem"
codex login
```

Чтобы настройка сохранялась между сеансами, добавьте строку `export` в `~/.zshrc` или `~/.bashrc`, а в Windows задайте переменную среды пользователя.

Что стоит знать о поведении этой настройки (по описанию [изменения #14239](https://github.com/openai/codex/pull/14239) в репозитории Codex, принятого 13 марта 2026 года):

- она действует не только на вход: её учитывают исходящие HTTPS-запросы и защищённые WebSocket-соединения, включая облачные задачи и HTTP-клиент MCP;
- порядок такой: `CODEX_CA_CERTIFICATE`, затем `SSL_CERT_FILE`, затем системные корневые сертификаты;
- ваш файл добавляется к системным корневым, а не заменяет их, поэтому в нём достаточно одного корпоративного корня;
- если файл не читается или повреждён, Codex выводит ошибку с именем переменной и путём — по ней видно, что настройка подхвачена.

Проверка результата: `codex login` завершается без ошибки, после чего короткий запрос в новом сеансе получает ответ. Если вместо этого вы видите сообщение о загрузке CA с путём к файлу, исправьте путь или формат файла.

Два случая, когда переменная не срабатывает:

1. Старая сборка CLI. Сборки до этого изменения доверяли только системным корневым сертификатам; у пользователя версии 0.58.0 та же причина давала при входе сообщение `Token exchange failed: error sending request for url (https://auth.openai.com/oauth/token)` — без слов про сертификат ([обращение #6849](https://github.com/openai/codex/issues/6849)). Обновите Codex и повторите. Остальные причины этого сообщения разобраны в материале про [ошибку Token Exchange Failed в Codex и поиск этапа сбоя](/ru/posts/codex-access-token-could-not-be-refreshed).
2. Переменная задана не в том окружении. Она действует только на процесс, который её унаследовал: терминал, открытый до правки `~/.zshrc`, или IDE, запущенная из Dock, о ней не знают. Перезапустите терминал; расширение IDE проверьте, запустив редактор из терминала, где переменная уже задана.

Вход по коду устройства (`codex login --device-auth`) проблему не обходит: он удобен на машинах без браузера, но обращается к тем же серверам по HTTPS и упирается в ту же проверку цепочки.

## Настольное приложение: Remote Control и NODE_USE_SYSTEM_CA=1

Для настольного приложения официального описания работы с собственным CA в документации Codex нет, есть сообщение пользователя. В [обращении #43489](https://github.com/openai/codex/issues/43489) от 7 сентября 2026 года (приложение 26.901.51231, macOS 26.6.1) описано следующее: в сети с инспекцией HTTPS функция Remote Control не подключается, в журнале остаются `SELF_SIGNED_CERT_IN_CHAIN` и строка `[remote-control-transport] remote_control_websocket.connect_failed_before_open`. При этом корневой сертификат компании доверен в системной связке ключей, а curl, OpenSSL и отдельно установленный Node проверяют цепочку успешно.

Автор обращения добился подключения, запустив приложение из терминала с переменной, которая заставляет Node читать системное хранилище:

```bash
NODE_USE_SYSTEM_CA=1 /Applications/ChatGPT.app/Contents/MacOS/ChatGPT
```

Это наблюдение одного пользователя: обращение открыто, ответа сопровождающих в нём нет, и в следующих сборках поведение может измениться. Сама переменная документирована в [справке Node.js](https://nodejs.org/api/cli.html): `NODE_USE_SYSTEM_CA=1` подключает хранилище операционной системы — связку ключей в macOS, хранилище сертификатов Windows, стандартные каталоги OpenSSL в Linux. Там же описана `NODE_EXTRA_CA_CERTS`: она добавляет сертификаты из PEM-файла к встроенным корневым и читается один раз при старте процесса.

Читает ли Node-слой приложения `CODEX_CA_CERTIFICATE` и как приложение ведёт себя в Windows и Linux, в открытых источниках не описано. Если запуск с `NODE_USE_SYSTEM_CA=1` не помогает, приложите к обращению в поддержку или к тому же issue строку из журнала и вывод `openssl s_client`. Когда приложение при этом ещё и теряет связь посреди работы, сначала сохраните состояние по инструкции [«Codex постоянно переподключается: сохраните задачу и найдите причину»](/ru/posts/codex-stuck-reconnecting-fix).

## MCP-серверы: подключение по url и отдельный процесс Node

У MCP-серверов два разных случая, и определяются они тем, как сервер описан в `config.toml`.

Сервер с ключом `url` вызывается HTTP-клиентом самого Codex. Этот клиент входит в список компонентов, на которые распространили `CODEX_CA_CERTIFICATE` и `SSL_CERT_FILE`, поэтому отдельной настройки не требуется: достаточно шага из предыдущего раздела. Так же решается ситуация, когда сервер развёрнут внутри компании и его сертификат выпущен частным CA: добавьте корень этого CA в тот же PEM-файл.

Сервер с ключом `command` — отдельный процесс. Если он написан на Node (типичный запуск через `npx`), то к внешним API он обращается сам и читает собственные настройки доверия. Передайте ему файл через таблицу `env` сервера, описанную в [документации по MCP](https://learn.chatgpt.com/docs/extend/mcp):

```toml
[mcp_servers.docs]
command = "npx"
args = ["-y", "example-mcp-server"]

[mcp_servers.docs.env]
NODE_EXTRA_CA_CERTS = "/Users/you/certs/corp-root-ca.pem"
```

Имя сервера и пакета здесь условные, путь к файлу укажите абсолютный. `NODE_EXTRA_CA_CERTS` читается при старте, поэтому после правки перезапустите Codex. Если файл повреждён, Node ограничится предупреждением и продолжит работу без него — при повторной ошибке проверьте файл командой `openssl x509` из раздела выше. Серверы на других языках читают свои настройки; для них ищите параметр CA в документации конкретного сервера.

## curl: (60) и npm в командах, которые запускает Codex

Команды, запущенные Codex, работают в песочнице и в отфильтрованном окружении, поэтому могут падать даже тогда, когда та же команда в обычном терминале проходит.

Первая причина описана в [обращении #11182](https://github.com/openai/codex/issues/11182) (9 февраля 2026 года, codex-cli 0.98.0, macOS). По разбору автора, системный curl на macOS для корневых сертификатов, которых нет в `/etc/ssl/cert.pem`, обращается к службе `com.apple.TrustEvaluationAgent`, чтобы проверить доверие по связке ключей. Песочница это обращение запрещает (отказ виден при запуске с `--log-denials`), и curl завершается с `curl: (60) SSL certificate problem: self signed certificate in certificate chain`. Обращение открыто, решения от сопровождающих в нём нет.

Обойтись без связки ключей можно штатным способом curl — указать файл с сертификатами явно. Обращение этот способ не проверяло, это стандартное поведение curl:

```bash
curl --cacert "$HOME/certs/corp-bundle.pem" https://example.internal/health
```

или через переменную `CURL_CA_BUNDLE`. В отличие от настройки Codex, curl этим файлом заменяет набор доверенных сертификатов, а не дополняет его. Если часть хостов идёт мимо инспекции, соберите общий файл:

```bash
cat /etc/ssl/cert.pem "$HOME/certs/corp-root-ca.pem" > "$HOME/certs/corp-bundle.pem"
```

Вторая причина — переменная не доходит до команды. Какие переменные окружения Codex передаёт запускаемым процессам, определяет `shell_environment_policy` в `config.toml`, поэтому `export` в вашей оболочке ещё не гарантирует, что `npm` или `curl` внутри Codex увидят значение. Надёжнее задать значения явно через ключ `set` этой политики:

```toml
[shell_environment_policy]
set = { NODE_EXTRA_CA_CERTS = "/Users/you/certs/corp-root-ca.pem", CURL_CA_BUNDLE = "/Users/you/certs/corp-bundle.pem" }
```

`NODE_EXTRA_CA_CERTS` закрывает `npm` и остальные инструменты на Node. Остальные ключи политики и порядок их применения — в [разделе о расширенной конфигурации](https://learn.chatgpt.com/docs/config-file/config-advanced); как устроены границы самой песочницы, разобрано в статье [«Песочница Codex и config.toml: границы, подтверждения и сеть»](/ru/posts/codex-config-toml).

Проверка: попросите Codex выполнить `curl -sS -o /dev/null -w "%{http_code}\n" https://registry.npmjs.org/` — в ответе должен быть код HTTP, а не ошибка 60.

## Почему NODE_TLS_REJECT_UNAUTHORIZED=0 не исправляет ошибку

`NODE_TLS_REJECT_UNAUTHORIZED=0`, `npm config set strict-ssl false`, `curl -k` и `--insecure` не добавляют доверие к корпоративному сертификату — они выключают проверку целиком. Процесс после этого примет любой сертификат от любого узла на пути, а не только от прокси вашей компании. [Документация Node.js](https://nodejs.org/api/cli.html) прямо предупреждает, что значение `0` делает TLS-соединения уязвимыми для атаки «человек посередине».

Для Codex цена выше обычной: по этому соединению идут токены доступа (в `~/.codex/auth.json`, который документация советует беречь как пароль), исходный код и результаты команд. Переменная, заданная в профиле оболочки, к тому же действует на все процессы Node, а не только на тот, что упал. Файл с корневым сертификатом решает ту же задачу и оставляет проверку включённой.

![Две колонки: передача корневого сертификата через CODEX_CA_CERTIFICATE оставляет проверку включённой, NODE_TLS_REJECT_UNAUTHORIZED=0 выключает её и принимает любой сертификат](https://www.aifreeapi.com/posts/ru/codex-self-signed-certificate-in-certificate-chain/img/trust-vs-disable.webp)

## Когда остановиться и обратиться в ИТ-службу

Остановитесь и передайте вопрос ИТ-службе, если выполняется любое из условий:

- корневого сертификата нет в системном хранилище и вам его не выдают;
- издатель в выводе `openssl s_client` вам незнаком и не относится к компании;
- сертификат передан нужному процессу, проверка файла проходит, а ошибка остаётся или сменилась отказом прокси;
- политика компании запрещает менять настройки доверия на рабочем компьютере.

Обходить корпоративные средства защиты не нужно: у ИТ-службы есть два штатных решения — выдать корневой сертификат (и промежуточные, если они есть) или исключить нужные хосты из инспекции. Чтобы обращение решили с первого раза, приложите к нему:

1. точный текст ошибки и место, где она появилась (CLI, приложение, MCP-сервер, команда в песочнице);
2. хост из ошибки или журнала;
3. строки `s:` и `i:` из вывода `openssl s_client` для этого хоста;
4. версию Codex и операционной системы.

Файл `~/.codex/auth.json` и переменные с ключами в обращение не вставляйте.

## Короткие ответы об ошибке сертификата в Codex

### Почему браузер и curl работают, а Codex выдаёт ошибку сертификата?

Потому что они читают разные хранилища. Браузер и системный curl используют хранилище операционной системы, куда ИТ-служба уже добавила корпоративный корень. Клиент Codex получает дополнительный корневой сертификат через `CODEX_CA_CERTIFICATE`, Node без `NODE_USE_SYSTEM_CA=1` опирается на встроенный список, а команда в песочнице macOS может не дотянуться до связки ключей.

### Нужно ли переустанавливать Codex или входить заново?

Переустановка доверие к сертификату не меняет. Повторный вход нужен только после того, как переменная задана: выполните `codex login` в том же терминале. Если Codex при запуске ждёт и завершается по тайм-ауту, а не ошибкой сертификата, смотрите разбор [«Codex не загрузил cloud config bundle за 15 секунд: что проверить»](/ru/posts/codex-timeout).

### Почему ошибка сертификата появляется в Codex дома, без прокси?

Проверьте издателя той же командой `openssl s_client`. Вне корпоративной сети цепочку обычно переподписывает антивирус с проверкой HTTPS либо ошибка относится к вашему собственному шлюзу или MCP-серверу с сертификатом частного CA. В первом случае экспортируйте корневой сертификат антивируса, во втором — корень вашего CA, и передайте файл так же, как описано выше.
