Repository navigation
Conversation
The reqwest crate `0.13` removes the `rustls-tls-native-roots` feature and defaults the rustls backend to `rustls-platform-verifier` for root certificates. On macOS and Windows that verifier uses the operating system trust store and ignores `SSL_CERT_FILE`, which is a feature we explicitly need and test for. This change loads the native root certs with `rustls-native-certs` and passes them to reqwest through `tls_certs_only` to keep that support on every platform. reqwest 0.12 pulled in `rustls-native-certs` behind the removed feature, so this declares it directly. close #979
edmorley
left a comment
There was a problem hiding this comment.
I was thinking this might be a quick approve, however, Claude found some issues, and also the premise (macOS and Windows support) isn't something we need for buildpacks. So I'm not sure this is the best approach? The backend situation for reqwest is a bit complicated - I'd need to sit down and take a closer look to say any more.
Summary from Claude:
I don't think we need the rustls-native-certs workaround, and as written it causes a regression:
- One unparseable cert in the store breaks every download. With only the rustls backend enabled,
reqwest::Certificate::from_dernever fails (it just copies the bytes), so the.filter_map(... .ok())filters nothing.tls_certs_onlythen adds each root withRootCertStore::add(..)?, so a single cert rustls can't parse makesbuild()fail. reqwest 0.12 skipped such certs on purpose, and so doesrustls-platform-verifier. To reproduce on Linux, use anSSL_CERT_FILEbundle containing the badssl cert plus one junkCERTIFICATEblock. That passes onmainbut fails on this branch withreqwest::Error { kind: Builder, source: InvalidCertificate(BadEncoding) }. - On Linux, reqwest 0.13's default verifier already honours
SSL_CERT_FILE. There,rustls-platform-verifiercallsrustls_native_certs::load_native_certs()itself (source). Only macOS and Windows use the OS trust store instead, and buildpacks (and our CI) only run on Linux. So droppingtls_certs_onlyandrustls-native-certskeeps the 0.12 behaviour where it matters.test_self_signed_certificatewould then just need#[cfg(target_os = "linux")].
An alternative worth considering is switching download to ureq 3 with default-features = false, features = ["rustls", "platform-verifier"]. It uses ring by default without any global state, and the download dependency tree drops from 95 crates to 38 (no tokio, hyper or aws-lc). We already use it in libcnb-test and most of our buildpacks. On Linux it behaves the same, including in the bad-cert case.
The reqwest crate
0.13removes therustls-tls-native-rootsfeature and defaults the rustls backend torustls-platform-verifierfor root certificates. On macOS and Windows that verifier uses the operating system trust store and ignoresSSL_CERT_FILE, which is a feature we explicitly need and test for.This change loads the native root certs with
rustls-native-certsand passes them to reqwest throughtls_certs_onlyto keep that support on every platform. reqwest 0.12 pulled inrustls-native-certsbehind the removed feature, so this declares it directly.close #979