Repository: vercel/next.js
Pull request: Turbopack: Use webpki-root-certs in addition to rustls-platform-verifier on Linux for bare-bones Linux images without root CA stores

This should fix the user-reported issue here: https://github.com/vercel/next.js/pull/88290#issuecomment-3762940063

That issue occurs when building with bare-bones docker images that contain no root CA store.

It's inconvenient to test inside of a bare-bones docker image, but I did at least test this works on a normal (Debian) Linux install when fetching fonts for shadcn-ui.

Changed files:
filename: Cargo.lock
patch: @@ -610,7 +610,7 @@ dependencies = [
  "bitflags 2.9.1",
  "cexpr",
  "clang-sys",
- "itertools 0.10.5",
+ "itertools 0.12.1",
  "lazy_static",
  "lazycell",
  "log",
@@ -4641,7 +4641,7 @@ version = "0.50.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
 dependencies = [
- "windows-sys 0.60.2",
+ "windows-sys 0.61.2",
 ]
 
 [[package]]
@@ -5641,7 +5641,7 @@ dependencies = [
  "once_cell",
  "socket2 0.5.10",
  "tracing",
- "windows-sys 0.52.0",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
@@ -6247,7 +6247,7 @@ dependencies = [
  "security-framework 3.5.1",
  "security-framework-sys",
  "webpki-root-certs",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.2",
 ]
 
 [[package]]
@@ -9513,6 +9513,7 @@ dependencies = [
  "turbo-tasks-fs",
  "turbo-tasks-testing",
  "turbopack-core",
+ "webpki-root-certs",
 ]
 
 [[package]]

filename: turbopack/crates/turbo-tasks-fetch/Cargo.toml
patch: @@ -46,6 +46,16 @@ reqwest = { workspace = true, features = ["rustls"] }
 reqwest = { workspace = true, features = ["rustls-no-provider"] }
 rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] }
 
+# On Linux, we need to add webpki-roots, in case the user is building a bare-bones docker image that
+# does not contain any root certs (e.g. `oven/bun:slim`). See footnote #2 here:
+# https://github.com/rustls/rustls-platform-verifier/tree/93f729c6309680486d33f982e3ba3c42b976f774?tab=readme-ov-file#user-content-fn-3-7402e7116652999a2e8c2860b94080eb
+#
+# It would be more ideal to use the smaller `webpki-roots` crate instead of `webpki-root-certs`, but
+# API limitations of reqwest require us to get the full certificate:
+# https://github.com/seanmonstar/reqwest/discussions/2906#discussioncomment-15483148
+[target.'cfg(target_os = "linux")'.dependencies]
+webpki-root-certs = "1"
+
 # On Windows ARM64, use native-tls because rustls with ring has build issues.
 [target.'cfg(all(windows, target_arch = "aarch64"))'.dependencies]
 reqwest = { workspace = true, features = ["native-tls"] }

filename: turbopack/crates/turbo-tasks-fetch/src/client.rs
patch: @@ -62,6 +62,18 @@ impl FetchClientConfig {
         {
             builder = builder.tls_backend_native();
         }
+        #[cfg(target_os = "linux")]
+        {
+            // Add webpki_root_certs on Linux (in addition to reqwest's default
+            // `rustls-platform-verifier`), in case the user is building in a bare-bones docker
+            // image that does not contain any root certs (e.g. `oven/bun:slim`).
+            builder = builder.tls_certs_merge(webpki_root_certs::TLS_SERVER_ROOT_CERTS.iter().map(
+                |der| {
+                    reqwest::Certificate::from_der(der)
+                        .expect("webpki_root_certs should parse correctly")
+                },
+            ))
+        }
         builder.build()
     }
 }