You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Every HTTPS call fails behind a TLS-inspecting proxy because the clients trust only bundled webpki roots #1107
The docs, however, send proxy users to the standard variables. CLI_CONTRACT.md#L1104 says "use the standard HTTP_PROXY/HTTPS_PROXY/NO_PROXY vars, which the HTTP client honors", and docs/configuration.md#L35-L37 says the same. A TLS-inspecting proxy (the usual corporate setup) re-signs traffic with a private CA that the user can't add, so every HTTPS call fails. Plain CONNECT proxies work.
Proof by execution. I used a debug build at b762f41, run twice with identical results, behind a TLS-inspecting HTTPS proxy whose CA is in SSL_CERT_FILE:
curl completes the handshake through the same proxy and trusts the same bundle. socket-patch rejects the issuer. (--proxy-url points at an allowed host only so the request leaves the sandbox; the client and trust store are the ones every patch-API call uses.)
Symptoms
I found no open issue. Within one install, behavior is split:
scripts/install.sh downloads with curl (system trust), and the package-manager tools socket-patch spawns (npm, pip, go, mvn, …) use their own CA settings, so they all succeed;
the binary's own API, blob, vendoring-service, registry, telemetry and self-update calls all fail with UnknownIssuer.
Impact
Enterprise CI behind an inspecting proxy can't use scan, get, vendor, repair or --update at all, and nothing can be configured to fix it. The error names the certificate, not the proxy, so the documented HTTPS_PROXY advice reads as broken. The fix is small (one dependency feature plus one shared builder). It has one security-relevant default, below.
Trust roots = the bundled webpki roots ∪ the platform store. Use reqwest's rustls-tls-native-roots feature alongside rustls-tls-webpki-roots. rustls-native-certs honors SSL_CERT_FILE/SSL_CERT_DIR on Unix and reads the Windows and macOS system stores.
Optionally add an explicit extra-CA file (SOCKET_CA_FILE, or reuse NODE_EXTRA_CA_CERTS for the npm wrapper's users) appended with add_root_certificate. Leave it out if the platform store is enough.
Document the trust-store rule next to the HTTPS_PROXY line in CLI_CONTRACT.md and docs/configuration.md.
Adding the platform store widens trust from "Mozilla roots" to "Mozilla roots plus whatever the OS trusts", which is what curl, npm, pip and cargo already do. If maintainers want the Mozilla-only default kept, the alternative is the explicit SOCKET_CA_FILE knob alone. Either fixes the defect.
Size and scope
Cargo.toml (one feature), a new utils/http.rs (~40 lines), six call sites, and two doc paragraphs. Estimated diff: under 150 production lines.
Every production reqwest::Client is built through the one constructor. A text ratchet test fails on a new reqwest::Client::builder() outside it.
A unit test builds a client that trusts a test CA from SSL_CERT_FILE (or the explicit knob), and completes a handshake with a local TLS server whose certificate that CA signed. Without the CA, the handshake fails with UnknownIssuer.
The default build still trusts public endpoints with an empty SSL_CERT_FILE/system store (the webpki fallback).
CLI_CONTRACT.md and docs/configuration.md state how trust roots are chosen.
Existing api_client_errors_e2e, covgap_api_client and update tests stay green.
Priority: P3 → P2. Enterprise TLS-inspection environments cannot make any HTTPS request and have no supported CA configuration. This is a functional deployment blocker.
[agent] Triaged as priority:p3: a cross-cutting HTTP client change, not tied to a p1/p2 ecosystem. It isn't a duplicate, and I found no open PR for it. As the issue says, it overlaps the client builders touched by #676, #770 and PR #1041. This also needs a maintainer decision on the trust default (bundled webpki plus the platform store, or Mozilla-only plus an explicit SOCKET_CA_FILE) before a fix is claimed.
[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: discussion #560 register.
Kind: bug. Source: new finding; register C75.
Problem (main @
b762f41)The workspace builds reqwest with only the bundled Mozilla root set:
Cargo.toml#L30.In reqwest 0.12,
rustls-tlsmeansrustls-tls-webpki-roots. No production client builder adds a certificate or reads a CA setting:client.rs#L1988-L2008telemetry.rs#L294update/release.rs#L267andupdate/download.rs#L63vendor/registry_fetch.rs#L58grep -rn "add_root_certificate\|SSL_CERT" crates/*/srcreturns nothing.The docs, however, send proxy users to the standard variables.
CLI_CONTRACT.md#L1104says "use the standardHTTP_PROXY/HTTPS_PROXY/NO_PROXYvars, which the HTTP client honors", anddocs/configuration.md#L35-L37says the same. A TLS-inspecting proxy (the usual corporate setup) re-signs traffic with a private CA that the user can't add, so every HTTPS call fails. Plain CONNECT proxies work.Proof by execution. I used a debug build at
b762f41, run twice with identical results, behind a TLS-inspecting HTTPS proxy whose CA is inSSL_CERT_FILE:curl completes the handshake through the same proxy and trusts the same bundle. socket-patch rejects the issuer. (
--proxy-urlpoints at an allowed host only so the request leaves the sandbox; the client and trust store are the ones every patch-API call uses.)Symptoms
I found no open issue. Within one install, behavior is split:
scripts/install.shdownloads withcurl(system trust), and the package-manager tools socket-patch spawns (npm,pip,go,mvn, …) use their own CA settings, so they all succeed;UnknownIssuer.Impact
Enterprise CI behind an inspecting proxy can't use
scan,get,vendor,repairor--updateat all, and nothing can be configured to fix it. The error names the certificate, not the proxy, so the documentedHTTPS_PROXYadvice reads as broken. The fix is small (one dependency feature plus one shared builder). It has one security-relevant default, below.Proposed change
utils::http::client_builder(), which sets the trust roots. Route the six builders above through it, and delete the per-sitereqwest::Client::builder()calls (this overlaps Send telemetry through one Telemetry handle with a shared HTTP client instead of 19 track wrappers #770's shared telemetry client and Tracking: one retry primitive for the patch API client (JSON, vendor service, blob and diff) #676's retry primitive; take whichever lands first).rustls-tls-native-rootsfeature alongsiderustls-tls-webpki-roots.rustls-native-certshonorsSSL_CERT_FILE/SSL_CERT_DIRon Unix and reads the Windows and macOS system stores.SOCKET_CA_FILE, or reuseNODE_EXTRA_CA_CERTSfor the npm wrapper's users) appended withadd_root_certificate. Leave it out if the platform store is enough.HTTPS_PROXYline inCLI_CONTRACT.mdanddocs/configuration.md.Adding the platform store widens trust from "Mozilla roots" to "Mozilla roots plus whatever the OS trusts", which is what curl, npm, pip and cargo already do. If maintainers want the Mozilla-only default kept, the alternative is the explicit
SOCKET_CA_FILEknob alone. Either fixes the defect.Size and scope
Cargo.toml(one feature), a newutils/http.rs(~40 lines), six call sites, and two doc paragraphs. Estimated diff: under 150 production lines.Acceptance criteria
reqwest::Clientis built through the one constructor. A text ratchet test fails on a newreqwest::Client::builder()outside it.SSL_CERT_FILE(or the explicit knob), and completes a handshake with a local TLS server whose certificate that CA signed. Without the CA, the handshake fails withUnknownIssuer.SSL_CERT_FILE/system store (the webpki fallback).CLI_CONTRACT.mdanddocs/configuration.mdstate how trust roots are chosen.api_client_errors_e2e,covgap_api_clientand update tests stay green.Dependencies
Backlog review — 2026-10-08
Priority: P3 → P2. Enterprise TLS-inspection environments cannot make any HTTPS request and have no supported CA configuration. This is a functional deployment blocker.