Skip to content

Commit 4e3dec8

Browse files
committed
fix(ie-net): fix multi-process HTTPS by using native OS certificates #75
Root cause: webpki-roots 1.0.6 was missing some root CAs (notably SSL.com TLS Transit ECC CA R2 used by Cloudflare). This caused TLS handshake failure: "invalid peer certificate: UnknownIssuer". Fix: - Switch from with_webpki_roots() to with_native_roots() which loads certificates from the OS certificate store (/etc/ssl/certs/) - Add "native-tokio" feature to hyper-rustls - Improve error chain capture: walk source() chain for detailed TLS error messages instead of losing inner cause Multi-process HTTPS now works — the sandboxed network child can successfully complete TLS handshakes with external servers. The --single-process workaround is no longer needed.
1 parent 2183781 commit 4e3dec8

3 files changed

Lines changed: 13 additions & 3 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ wasmtime = "31"
4646
hyper = { version = "1", features = ["full"] }
4747
hyper-util = { version = "0.1", features = ["full"] }
4848
http-body-util = "0.1"
49-
hyper-rustls = { version = "0.27", features = ["http2", "webpki-roots"] }
49+
hyper-rustls = { version = "0.27", features = ["http2", "webpki-roots", "native-tokio"] }
5050
rustls = "0.23"
5151
url = "2"
5252
serde = { version = "1", features = ["derive"] }

crates/ie-net/src/client.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ pub struct Client {
2424

2525
impl Client {
2626
pub fn new() -> Result<Self, NetError> {
27+
// Use native OS certificates with webpki-roots as fallback
2728
let connector = HttpsConnectorBuilder::new()
28-
.with_webpki_roots()
29+
.with_native_roots()
30+
.map_err(|e| NetError::TlsError(format!("failed to load native certs: {e}")))?
2931
.https_or_http()
3032
.enable_http1()
3133
.enable_http2()
@@ -88,7 +90,14 @@ impl Client {
8890
.map_err(|e| NetError::ConnectionFailed(e.to_string()))?;
8991

9092
let resp = self.inner.request(req).await.map_err(|e| {
91-
let msg = e.to_string();
93+
// Capture full error chain for debugging
94+
use std::error::Error as _;
95+
let mut msg = e.to_string();
96+
let mut source: Option<&dyn std::error::Error> = e.source();
97+
while let Some(inner) = source {
98+
msg.push_str(&format!(" → {inner}"));
99+
source = inner.source();
100+
}
92101
if msg.contains("tls") || msg.contains("ssl") || msg.contains("certificate") {
93102
NetError::TlsError(msg)
94103
} else {

crates/ie-shell/src/child_network.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub async fn run_network_process(mut channel: IpcChannel) -> Result<()> {
2828
.await?;
2929
}
3030
Err(e) => {
31+
tracing::error!("fetch failed: {e:?}");
3132
channel
3233
.send(&IpcMessage::FetchError {
3334
id,

0 commit comments

Comments
 (0)