From 4c8a6e09deb9518db9de8b65c6f12a2e3ffa7fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=82=98=ED=98=95=EC=A7=84?= Date: Sat, 29 Aug 2026 16:26:16 +0900 Subject: [PATCH] fix(tls): trust OS root certificates for wss connections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every wss client in the workspace builds its rustls trust store from webpki-roots alone, so it ignores the operating system trust store. On a machine behind a TLS-inspecting proxy — where the OS store holds the proxy's CA but the bundled Mozilla roots do not — connecting fails with: WebSocket connection failed: IO error: invalid peer certificate: UnknownIssuer Desktop pairing (desktop/src-tauri/src/commands/pairing.rs) surfaces this straight to the user: the pairing QR code never renders, so the phone cannot be paired at all. Enable rustls-tls-native-roots alongside the existing rustls-tls-webpki-roots rather than replacing it. tokio-tungstenite merges both sources into one root store and only treats an empty native store as fatal when webpki roots are absent, so hosts without a system trust store (minimal containers) keep behaving exactly as they do today. rustls-native-certs additionally honors SSL_CERT_FILE and SSL_CERT_DIR, which gives operators a supported way to supply a custom CA. No call sites change: the remaining crates inherit the dependency through `workspace = true`. rustls-native-certs was already present in both lockfiles, so this adds a dependency edge rather than a new package. Trade-off: this widens the client's trust scope to whatever the host already trusts — the same posture browsers and curl take on these machines. That is the intent, and it is why the change is opt-out by uninstalling the CA rather than opt-in per connection. Scope: this covers Buzz's own wss paths (tokio-tungstenite 0.29). The mesh compute path reaches the network through nostr-sdk -> async-wsocket, which resolves a separate tokio-tungstenite 0.28 and is untouched here. Fixes #5197 Fixes #2940 Signed-off-by: 나형진 Co-authored-by: Claude --- Cargo.lock | 1 + Cargo.toml | 6 +++++- desktop/src-tauri/Cargo.lock | 1 + desktop/src-tauri/Cargo.toml | 3 ++- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9544a63b899..c07772fe232 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9893,6 +9893,7 @@ dependencies = [ "futures-util", "log", "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", diff --git a/Cargo.toml b/Cargo.toml index d6ee839f1b0..58244b3d88b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -125,7 +125,11 @@ moka = { version = "0.12", features = ["sync"] } futures-util = "0.3" # WebSocket client (test client) -tokio-tungstenite = { version = "0.29", features = ["rustls-tls-webpki-roots"] } +# Both root sources on purpose. Native roots let wss:// work where the OS trusts a +# CA the Mozilla bundle does not (TLS-inspecting proxies), and honor SSL_CERT_FILE. +# Keeping webpki roots means an empty native store is not fatal, so hosts without a +# system trust store — minimal containers — behave as they do today. +tokio-tungstenite = { version = "0.29", features = ["rustls-tls-webpki-roots", "rustls-tls-native-roots"] } url = "2" # Property-based testing (dev-only) diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock index 68b702431af..507c9360a0d 100644 --- a/desktop/src-tauri/Cargo.lock +++ b/desktop/src-tauri/Cargo.lock @@ -11227,6 +11227,7 @@ dependencies = [ "futures-util", "log", "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml index f41fa2d6e39..be64c9c8483 100644 --- a/desktop/src-tauri/Cargo.toml +++ b/desktop/src-tauri/Cargo.toml @@ -83,7 +83,8 @@ infer = "0.19" hex = "0.4" ed25519-dalek = "=3.0.0-rc.0" tokio = { version = "1", features = ["fs", "sync", "rt", "macros", "time", "net", "io-util"] } -tokio-tungstenite = { version = "0.29", features = ["rustls-tls-webpki-roots"] } +# Root sources kept in sync with the workspace manifest; see the comment there. +tokio-tungstenite = { version = "0.29", features = ["rustls-tls-webpki-roots", "rustls-tls-native-roots"] } tokio-util = { version = "0.7", features = ["rt"] } bytes = "1" futures-util = "0.3"