MacOS programs fail to communicate with hosts using esoteric root certificates when in Codex sandbox
What version of Codex CLI is running?
codex-cli 0.98.0
What subscription do you have?
Plus
Which model were you using?
GPT-5.3-Codex
What platform is your computer?
Darwin 24.3.0 arm64 arm
What terminal emulator and version are you using (if applicable)?
Terminal.app
What issue are you seeing?
When in Codex sandbox, some built-in Mac OS programs cannot make TLS connections to hosts which rely on certain root certificates, which are otherwise accepted by Mac OS. This issue definitely affects curl, resulting in the following (extremely misleading) message:
curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
As explained below, the issue is not specific to curl, and affects all tools that rely on the Openssl stack shipped with Mac OS.
What steps can reproduce the bug?
# first, lets set up an alias to make sandbox runs easier
$ alias cs="codex sandbox macos --log-denials --full-auto"
# config should look like the following:
$ cat ~/.codex/config.toml
# [snip...]
[sandbox_workspace_write]
network_access = true
# let's try connecting to a problematic host:
$ cs curl 'https://services.clarin-pl.eu'
curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
=== Sandbox denials ===
(curl) sysctl-read kern.bootargs
(curl) file-write-data /dev/dtracehelper
(curl) mach-lookup com.apple.logd
(curl) mach-lookup com.apple.system.notification_center
(curl) mach-lookup com.apple.TrustEvaluationAgent # !!![1]
# now, let's try without the sandbox to verify that this is not a server issue:
$ curl 'https://services.clarin-pl.eu'
(lots of HTML output)
# Now let's try a sandboxed curl to a different host to verify that it's not a network access issue
$ cs curl 'https://google.com'
<html><head>[...] # lots of output
=== Sandbox denials ===
(curl) sysctl-read kern.bootargs
(curl) file-write-data /dev/dtracehelper
(curl) mach-lookup com.apple.logd
(curl) mach-lookup com.apple.system.notification_center
# Notice no com.apple.trustEvaluationAgent here?
# Now, let's see the certificate chains for those two respective hosts:
# (use homebrew openssl, which ships its own root CA store)
$ /opt/homebrew/bin/openssl s_client -connect services.clarin-pl.eu:443 -servername services.clarin-pl.eu -showcerts </dev/null
Connecting to 156.17.249.252
depth=2 C=PL, O=Asseco Data Systems S.A., OU=Certum Certification Authority, CN=Certum EC-384 CA
verify return:1
depth=1 C=PL, O=nazwa.pl Sp. z o.o., CN=nazwaSSL DV TLS G2 E29 CA
verify return:1
depth=0 CN=*.clarin-pl.eu
verify return:1
CONNECTED(00000005)
---
Certificate chain
0 s:CN=*.clarin-pl.eu
i:C=PL, O=nazwa.pl Sp. z o.o., CN=nazwaSSL DV TLS G2 E29 CA
a:PKEY: EC, (secp384r1); sigalg: ecdsa-with-SHA384
v:NotBefore: Nov 28 09:29:09 2025 GMT; NotAfter: Nov 27 00:00:00 2026 GMT
-----BEGIN CERTIFICATE-----
[...] # lots of base64 output here
-----END CERTIFICATE-----
1 s:C=PL, O=nazwa.pl Sp. z o.o., CN=nazwaSSL DV TLS G2 E29 CA
i:C=PL, O=Asseco Data Systems S.A., OU=Certum Certification Authority, CN=Certum EC-384 CA
a:PKEY: EC, (secp384r1); sigalg: ecdsa-with-SHA384
v:NotBefore: Aug 20 09:37:15 2024 GMT; NotAfter: Aug 14 09:37:15 2029 GMT
-----BEGIN CERTIFICATE-----
[...] # lots of base64 output here
-----END CERTIFICATE-----
2 s:C=PL, O=Asseco Data Systems S.A., OU=Certum Certification Authority, CN=Certum EC-384 CA
i:C=PL, O=Asseco Data Systems S.A., OU=Certum Certification Authority, CN=Certum EC-384 CA
a:PKEY: EC, (secp384r1); sigalg: ecdsa-with-SHA384
v:NotBefore: Mar 26 07:24:54 2018 GMT; NotAfter: Mar 26 07:24:54 2043 GMT
-----BEGIN CERTIFICATE-----
[...] # lots of base64 output here
-----END CERTIFICATE-----
---
Server certificate
subject=CN=*.clarin-pl.eu
issuer=C=PL, O=nazwa.pl Sp. z o.o., CN=nazwaSSL DV TLS G2 E29 CA
---
No client certificate CA names sent
Peer signing digest: SHA384
Peer signature type: ecdsa_secp384r1_sha384
Peer Temp Key: X25519, 253 bits
---
SSL handshake has read 3111 bytes and written 1632 bytes
Verification: OK # !!!
[...] # some more output here
# And now Google...
Connecting to 142.250.130.100
depth=2 C=US, O=Google Trust Services LLC, CN=GTS Root R4
verify return:1
depth=1 C=US, O=Google Trust Services, CN=WE2
verify return:1
depth=0 CN=*.google.com
verify return:1
CONNECTED(00000005)
---
Certificate chain
0 s:CN=*.google.com
i:C=US, O=Google Trust Services, CN=WE2
a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA256
v:NotBefore: Jan 19 08:37:03 2026 GMT; NotAfter: Apr 13 08:37:02 2026 GMT
-----BEGIN CERTIFICATE-----
[...] # lots of base64 output here
-----END CERTIFICATE-----
1 s:C=US, O=Google Trust Services, CN=WE2
i:C=US, O=Google Trust Services LLC, CN=GTS Root R4
a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA384
v:NotBefore: Dec 13 09:00:00 2023 GMT; NotAfter: Feb 20 14:00:00 2029 GMT
-----BEGIN CERTIFICATE-----
[...] # lots of base64 output here
-----END CERTIFICATE-----
2 s:C=US, O=Google Trust Services LLC, CN=GTS Root R4
i:C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
a:PKEY: EC, (secp384r1); sigalg: sha256WithRSAEncryption
v:NotBefore: Nov 15 03:43:21 2023 GMT; NotAfter: Jan 28 00:00:42 2028 GMT
-----BEGIN CERTIFICATE-----
[...] # lots of base64 output here
-----END CERTIFICATE-----
---
Server certificate
subject=CN=*.google.com
issuer=C=US, O=Google Trust Services, CN=WE2
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ecdsa_secp256r1_sha256
Negotiated TLS1.3 group: X25519MLKEM768
---
SSL handshake has read 6420 bytes and written 1621 bytes
Verification: OK # !!!
# now let's check which of these root certificates Apple ships in /etc/ssl/cert.pem,
# and which are in the system keychain only
$openssl crl2pkcs7 -nocrl -certfile /etc/ssl/cert.pem | openssl pkcs7 -print_certs -text -noout | grep 'GTS Root R4'
Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R4
Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R4
# great, the cert is there
# and now the other one
$openssl crl2pkcs7 -nocrl -certfile /etc/ssl/cert.pem | openssl pkcs7 -print_certs -text -noout | grep 'Certum'
Issuer: C=PL, O=Unizeto Technologies S.A., OU=Certum Certification Authority, CN=Certum Trusted Network CA
Subject: C=PL, O=Unizeto Technologies S.A., OU=Certum Certification Authority, CN=Certum Trusted Network CA
# This is not that cert (notice Asseco versus Unizeto)?
What is the expected behavior?
TLS connections to hosts with this problem should succeed if network access is enabled, just as they do outside the sandbox.
To do this, Codex should be allowed to communicate with com.apple.TrustEvaluationAgent when network access is enabled (one would have to do a security analysis of this binary to determine whether that is safe). Alternatively, Codex should generate a more descriptive error when a command fails and communication with this daemon has been attempted during its execution.
Additional information
What's actually going on here is that Apple has patched their Openssl to rely on the system trust store (accessed via communicating with com.apple.TrustEvaluationAgent) in case verifying a TLS certificate via /etc/ssl/cert.pem fails. FOr some reason (which I haven't been able to establish), some certificates in common use on the public web are properly shipped with Mac OS in the system keychain, but are not shipped in /etc/ssl/cert.pem. Certum's EC384 root certificate is the one example I found, and this certificate is relied upon by nazwa.pl, a common hosting provider for websites in Poland, but there are likely others.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗