From 66a75ece27ee2f4e7364ef9ddc8db6cbeeb56919 Mon Sep 17 00:00:00 2001 From: Fabian-Lars Date: Tue, 25 Nov 2025 20:02:47 +0100 Subject: [PATCH] fix(websocket): install crypto provider if needed (#3124) --- .changes/websocket-default-provider.md | 6 +++ Cargo.lock | 1 + plugins/websocket/Cargo.toml | 10 ++++- plugins/websocket/src/lib.rs | 51 ++++++++++++++++++++++---- 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 .changes/websocket-default-provider.md diff --git a/.changes/websocket-default-provider.md b/.changes/websocket-default-provider.md new file mode 100644 index 000000000..7c956e214 --- /dev/null +++ b/.changes/websocket-default-provider.md @@ -0,0 +1,6 @@ +--- +websocket: patch:bug +websocket-js: patch:bug +--- + +The WebSocket plugin will now install the default crypto provider if needed, preventing panics on WSS connections. diff --git a/Cargo.lock b/Cargo.lock index 0d424c660..4861ccf82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6965,6 +6965,7 @@ dependencies = [ "http", "log", "rand 0.9.0", + "rustls", "serde", "serde_json", "tauri", diff --git a/plugins/websocket/Cargo.toml b/plugins/websocket/Cargo.toml index daadea42b..387218bb8 100644 --- a/plugins/websocket/Cargo.toml +++ b/plugins/websocket/Cargo.toml @@ -31,10 +31,16 @@ rand = "0.9" futures-util = "0.3" tokio = { version = "1", features = ["net", "sync"] } tokio-tungstenite = { version = "0.28" } +rustls = { version = "0.23", default-features = false, features = [ + "ring", +], optional = true } [features] default = ["rustls-tls"] native-tls = ["tokio-tungstenite/native-tls"] native-tls-vendored = ["native-tls", "tokio-tungstenite/native-tls-vendored"] -rustls-tls = ["tokio-tungstenite/rustls-tls-webpki-roots"] -rustls-tls-native-roots = ["tokio-tungstenite/rustls-tls-native-roots"] +rustls-tls = ["tokio-tungstenite/rustls-tls-webpki-roots", "dep:rustls"] +rustls-tls-native-roots = [ + "tokio-tungstenite/rustls-tls-native-roots", + "dep:rustls", +] diff --git a/plugins/websocket/src/lib.rs b/plugins/websocket/src/lib.rs index f75817b61..9743e2cde 100644 --- a/plugins/websocket/src/lib.rs +++ b/plugins/websocket/src/lib.rs @@ -18,9 +18,17 @@ use tauri::{ Manager, Runtime, State, Window, }; use tokio::{net::TcpStream, sync::Mutex}; -#[cfg(any(feature = "rustls-tls", feature = "native-tls"))] +#[cfg(any( + feature = "rustls-tls", + feature = "rustls-tls-native-roots", + feature = "native-tls" +))] use tokio_tungstenite::connect_async_tls_with_config; -#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))] +#[cfg(not(any( + feature = "rustls-tls", + feature = "rustls-tls-native-roots", + feature = "native-tls" +)))] use tokio_tungstenite::connect_async_with_config; use tokio_tungstenite::{ tungstenite::{ @@ -63,7 +71,11 @@ impl Serialize for Error { #[derive(Default)] struct ConnectionManager(Mutex>); -#[cfg(any(feature = "rustls-tls", feature = "native-tls"))] +#[cfg(any( + feature = "rustls-tls", + feature = "rustls-tls-native-roots", + feature = "native-tls" +))] struct TlsConnector(Mutex>); #[derive(Deserialize)] @@ -157,17 +169,29 @@ async fn connect( } } - #[cfg(any(feature = "rustls-tls", feature = "native-tls"))] + #[cfg(any( + feature = "rustls-tls", + feature = "rustls-tls-native-roots", + feature = "native-tls" + ))] let tls_connector = match window.try_state::() { Some(tls_connector) => tls_connector.0.lock().await.clone(), None => None, }; - #[cfg(any(feature = "rustls-tls", feature = "native-tls"))] + #[cfg(any( + feature = "rustls-tls", + feature = "rustls-tls-native-roots", + feature = "native-tls" + ))] let (ws_stream, _) = connect_async_tls_with_config(request, config.map(Into::into), false, tls_connector) .await?; - #[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))] + #[cfg(not(any( + feature = "rustls-tls", + feature = "rustls-tls-native-roots", + feature = "native-tls" + )))] let (ws_stream, _) = connect_async_with_config(request, config.map(Into::into), false).await?; tauri::async_runtime::spawn(async move { @@ -266,8 +290,21 @@ impl Builder { PluginBuilder::new("websocket") .invoke_handler(tauri::generate_handler![connect, send]) .setup(|app, _api| { + #[cfg(any(feature = "rustls-tls", feature = "rustls-tls-native-roots"))] + if (self.tls_connector.is_none() + || matches!(self.tls_connector, Some(Connector::Plain))) + && rustls::crypto::CryptoProvider::get_default().is_none() + { + // This can only fail if there is already a default provider which we checked for already. + let _ = rustls::crypto::ring::default_provider().install_default(); + } + app.manage(ConnectionManager::default()); - #[cfg(any(feature = "rustls-tls", feature = "native-tls"))] + #[cfg(any( + feature = "rustls-tls", + feature = "rustls-tls-native-roots", + feature = "native-tls" + ))] app.manage(TlsConnector(Mutex::new(self.tls_connector))); Ok(()) })