From d5a8117e087fc1201cf059a2add082e7529022e3 Mon Sep 17 00:00:00 2001 From: malsamiri-oai Date: Mon, 15 Jun 2026 11:32:13 -0700 Subject: [PATCH] Use aws-lc-rs for rustls crypto provider (#27706) ## Why Some enterprise TLS proxies issue certificate chains signed with `ecdsa_secp521r1_sha512` / `ECDSA_NISTP521_SHA512`. Custom CA configuration such as `SSL_CERT_FILE` can add the right trust root, but it cannot make `rustls`'s `ring` verifier support a certificate signature algorithm it does not advertise. That can still break TLS after the CA bundle is configured, including on Rust websocket paths that call the shared `ensure_rustls_crypto_provider()` helper, such as the Responses websocket connector and remote app-server client: - [`codex-api/src/endpoint/responses_websocket.rs`](https://github.com/openai/codex/blob/eddc5c75ed527a8348bfcaa85692e53189600833/codex-rs/codex-api/src/endpoint/responses_websocket.rs#L441) - [`app-server-client/src/remote.rs`](https://github.com/openai/codex/blob/eddc5c75ed527a8348bfcaa85692e53189600833/codex-rs/app-server-client/src/remote.rs#L718) The `aws-lc-rs` `rustls` provider supports this P-521/SHA-512 certificate signature scheme, so use it as Codex's process-wide `rustls` provider. ## What Changed - Switch the workspace `rustls` feature from `ring` to `aws_lc_rs`. - Update `codex-utils-rustls-provider` to install `rustls::crypto::aws_lc_rs::default_provider()`. - Add an assertion and integration test that the installed provider supports `ECDSA_NISTP521_SHA512`. ## Verification ```shell just fmt just test -p codex-utils-rustls-provider just bazel-lock-update just bazel-lock-check ``` --- codex-rs/Cargo.toml | 2 +- codex-rs/utils/rustls-provider/src/lib.rs | 29 ++++++++++++++++++- .../rustls-provider/tests/preinstalled.rs | 26 +++++++++++++++++ .../utils/rustls-provider/tests/provider.rs | 16 ++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 codex-rs/utils/rustls-provider/tests/preinstalled.rs create mode 100644 codex-rs/utils/rustls-provider/tests/provider.rs diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index dfb89a02c..fcf8dbd9c 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -363,7 +363,7 @@ reqwest = { version = "0.12", features = ["cookies"] } rmcp = { version = "1.7.0", default-features = false } runfiles = { git = "https://github.com/dzbarsky/rules_rust", rev = "b56cbaa8465e74127f1ea216f813cd377295ad81" } rustls = { version = "0.23", default-features = false, features = [ - "ring", + "aws_lc_rs", "std", ] } rustls-native-certs = "0.8.3" diff --git a/codex-rs/utils/rustls-provider/src/lib.rs b/codex-rs/utils/rustls-provider/src/lib.rs index 39d01d182..0269819ba 100644 --- a/codex-rs/utils/rustls-provider/src/lib.rs +++ b/codex-rs/utils/rustls-provider/src/lib.rs @@ -1,5 +1,8 @@ use std::sync::Once; +const REQUIRED_SIGNATURE_SCHEME: rustls::SignatureScheme = + rustls::SignatureScheme::ECDSA_NISTP521_SHA512; + /// Ensures a process-wide rustls crypto provider is installed. /// /// rustls cannot auto-select a provider when both `ring` and `aws-lc-rs` @@ -7,6 +10,30 @@ use std::sync::Once; pub fn ensure_rustls_crypto_provider() { static RUSTLS_PROVIDER_INIT: Once = Once::new(); RUSTLS_PROVIDER_INIT.call_once(|| { - let _ = rustls::crypto::ring::default_provider().install_default(); + // aws-lc-rs supports a broader WebPKI signature set than ring, including + // ECDSA P-521/SHA-512 certs used by some enterprise TLS proxies. + if rustls::crypto::aws_lc_rs::default_provider() + .install_default() + .is_err() + { + // Preserve the previous best-effort behavior for embedded hosts that + // install a process-global provider before Codex can install one. + return; + } + + let Some(provider) = rustls::crypto::CryptoProvider::get_default() else { + panic!("aws-lc-rs rustls crypto provider should be installed"); + }; + assert!( + provider_supports_required_signature_scheme(provider), + "installed rustls crypto provider must support {REQUIRED_SIGNATURE_SCHEME:?}" + ); }); } + +fn provider_supports_required_signature_scheme(provider: &rustls::crypto::CryptoProvider) -> bool { + provider + .signature_verification_algorithms + .supported_schemes() + .contains(&REQUIRED_SIGNATURE_SCHEME) +} diff --git a/codex-rs/utils/rustls-provider/tests/preinstalled.rs b/codex-rs/utils/rustls-provider/tests/preinstalled.rs new file mode 100644 index 000000000..714f40bf6 --- /dev/null +++ b/codex-rs/utils/rustls-provider/tests/preinstalled.rs @@ -0,0 +1,26 @@ +use codex_utils_rustls_provider::ensure_rustls_crypto_provider; + +const EMPTY_ALGORITHMS: rustls::crypto::WebPkiSupportedAlgorithms = + rustls::crypto::WebPkiSupportedAlgorithms { + all: &[], + mapping: &[], + }; + +#[test] +fn ensure_provider_preserves_preinstalled_provider() { + let mut provider = rustls::crypto::aws_lc_rs::default_provider(); + provider.signature_verification_algorithms = EMPTY_ALGORITHMS; + assert!(provider.install_default().is_ok()); + + ensure_rustls_crypto_provider(); + + let Some(provider) = rustls::crypto::CryptoProvider::get_default() else { + panic!("preinstalled rustls provider should still be installed"); + }; + assert!( + !provider + .signature_verification_algorithms + .supported_schemes() + .contains(&rustls::SignatureScheme::ECDSA_NISTP521_SHA512) + ); +} diff --git a/codex-rs/utils/rustls-provider/tests/provider.rs b/codex-rs/utils/rustls-provider/tests/provider.rs new file mode 100644 index 000000000..c02f884e0 --- /dev/null +++ b/codex-rs/utils/rustls-provider/tests/provider.rs @@ -0,0 +1,16 @@ +use codex_utils_rustls_provider::ensure_rustls_crypto_provider; + +#[test] +fn ensure_provider_installs_ecdsa_p521_sha512_support() { + ensure_rustls_crypto_provider(); + + let Some(provider) = rustls::crypto::CryptoProvider::get_default() else { + panic!("rustls provider should be installed"); + }; + assert!( + provider + .signature_verification_algorithms + .supported_schemes() + .contains(&rustls::SignatureScheme::ECDSA_NISTP521_SHA512) + ); +}