feat(core): block remote URLs from accessing the IPC

This was cherry picked from ee71c31fd0, keeping only the logic to block remote URLs from using the IPC.
PR: #5918
This commit is contained in:
Lucas Nogueira 2023-04-12 11:43:57 -03:00
parent 34e03b8455
commit fa90214b05
No known key found for this signature in database
GPG Key ID: FFEA6C72E73482F1
12 changed files with 128 additions and 57 deletions

7
.changes/remote-urls.md Normal file
View File

@ -0,0 +1,7 @@
---
"tauri": patch
"tauri-runtime": patch
"tauri-runtime-wry": patch
---
Block remote URLs from accessing the IPC.

View File

@ -54,5 +54,5 @@ fn override_msvcrt_lib() {
f.write_all(bytes).unwrap(); f.write_all(bytes).unwrap();
} }
// Add the output directory to the native library path. // Add the output directory to the native library path.
println!("cargo:rustc-link-search=native={}", out_dir); println!("cargo:rustc-link-search=native={out_dir}");
} }

View File

@ -19,6 +19,7 @@ tauri-utils = { version = "1.0.3", path = "../tauri-utils" }
uuid = { version = "1", features = [ "v4" ] } uuid = { version = "1", features = [ "v4" ] }
rand = "0.8" rand = "0.8"
raw-window-handle = "0.4.3" raw-window-handle = "0.4.3"
url = "2"
[target."cfg(windows)".dependencies] [target."cfg(windows)".dependencies]
webview2-com = "0.16.0" webview2-com = "0.16.0"

View File

@ -41,6 +41,7 @@ use wry::application::platform::windows::{WindowBuilderExtWindows, WindowExtWind
use wry::application::system_tray::{SystemTray as WrySystemTray, SystemTrayBuilder}; use wry::application::system_tray::{SystemTray as WrySystemTray, SystemTrayBuilder};
use tauri_utils::{config::WindowConfig, debug_eprintln, Theme}; use tauri_utils::{config::WindowConfig, debug_eprintln, Theme};
use url::Url;
use uuid::Uuid; use uuid::Uuid;
use wry::{ use wry::{
application::{ application::{
@ -216,6 +217,7 @@ impl<T: UserEvent> Context<T> {
impl<T: UserEvent> Context<T> { impl<T: UserEvent> Context<T> {
fn create_webview(&self, pending: PendingWindow<T, Wry<T>>) -> Result<DetachedWindow<T, Wry<T>>> { fn create_webview(&self, pending: PendingWindow<T, Wry<T>>) -> Result<DetachedWindow<T, Wry<T>>> {
let label = pending.label.clone(); let label = pending.label.clone();
let current_url = pending.current_url.clone();
let menu_ids = pending.menu_ids.clone(); let menu_ids = pending.menu_ids.clone();
let js_event_listeners = pending.js_event_listeners.clone(); let js_event_listeners = pending.js_event_listeners.clone();
let context = self.clone(); let context = self.clone();
@ -237,6 +239,7 @@ impl<T: UserEvent> Context<T> {
}; };
Ok(DetachedWindow { Ok(DetachedWindow {
label, label,
current_url,
dispatcher, dispatcher,
menu_ids, menu_ids,
js_event_listeners, js_event_listeners,
@ -1862,6 +1865,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>> { fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>> {
let label = pending.label.clone(); let label = pending.label.clone();
let current_url = pending.current_url.clone();
let menu_ids = pending.menu_ids.clone(); let menu_ids = pending.menu_ids.clone();
let js_event_listeners = pending.js_event_listeners.clone(); let js_event_listeners = pending.js_event_listeners.clone();
let window_id = rand::random(); let window_id = rand::random();
@ -1889,6 +1893,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
Ok(DetachedWindow { Ok(DetachedWindow {
label, label,
current_url,
dispatcher, dispatcher,
menu_ids, menu_ids,
js_event_listeners, js_event_listeners,
@ -2833,7 +2838,7 @@ fn create_webview<T: UserEvent>(
mut window_builder, mut window_builder,
ipc_handler, ipc_handler,
label, label,
url, current_url,
menu_ids, menu_ids,
js_event_listeners, js_event_listeners,
.. ..
@ -2871,16 +2876,22 @@ fn create_webview<T: UserEvent>(
} }
let mut webview_builder = WebViewBuilder::new(window) let mut webview_builder = WebViewBuilder::new(window)
.map_err(|e| Error::CreateWebview(Box::new(e)))? .map_err(|e| Error::CreateWebview(Box::new(e)))?
.with_url(&url) .with_url(current_url.lock().unwrap().as_str())
.unwrap() // safe to unwrap because we validate the URL beforehand .unwrap() // safe to unwrap because we validate the URL beforehand
.with_transparent(is_window_transparent); .with_transparent(is_window_transparent);
if webview_attributes.file_drop_handler_enabled { if webview_attributes.file_drop_handler_enabled {
webview_builder = webview_builder.with_file_drop_handler(create_file_drop_handler(&context)); webview_builder = webview_builder.with_file_drop_handler(create_file_drop_handler(&context));
} }
if let Some(navigation_handler) = pending.navigation_handler {
webview_builder = webview_builder.with_navigation_handler(move |url| {
Url::parse(&url).map(&navigation_handler).unwrap_or(true)
});
}
if let Some(handler) = ipc_handler { if let Some(handler) = ipc_handler {
webview_builder = webview_builder.with_ipc_handler(create_ipc_handler( webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
context, context,
label.clone(), label.clone(),
current_url,
menu_ids, menu_ids,
js_event_listeners, js_event_listeners,
handler, handler,
@ -2984,6 +2995,7 @@ fn create_webview<T: UserEvent>(
fn create_ipc_handler<T: UserEvent>( fn create_ipc_handler<T: UserEvent>(
context: Context<T>, context: Context<T>,
label: String, label: String,
current_url: Arc<Mutex<Url>>,
menu_ids: Arc<Mutex<HashMap<MenuHash, MenuId>>>, menu_ids: Arc<Mutex<HashMap<MenuHash, MenuId>>>,
js_event_listeners: Arc<Mutex<HashMap<JsEventListenerKey, HashSet<u64>>>>, js_event_listeners: Arc<Mutex<HashMap<JsEventListenerKey, HashSet<u64>>>>,
handler: WebviewIpcHandler<T, Wry<T>>, handler: WebviewIpcHandler<T, Wry<T>>,
@ -2992,6 +3004,7 @@ fn create_ipc_handler<T: UserEvent>(
let window_id = context.webview_id_map.get(&window.id()); let window_id = context.webview_id_map.get(&window.id());
handler( handler(
DetachedWindow { DetachedWindow {
current_url: current_url.clone(),
dispatcher: WryDispatcher { dispatcher: WryDispatcher {
window_id, window_id,
context: context.clone(), context: context.clone(),

View File

@ -32,6 +32,7 @@ http = "0.2.4"
http-range = "0.1.4" http-range = "0.1.4"
infer = "0.7" infer = "0.7"
raw-window-handle = "0.4.3" raw-window-handle = "0.4.3"
url = "2"
[target."cfg(windows)".dependencies] [target."cfg(windows)".dependencies]
webview2-com = "0.16.0" webview2-com = "0.16.0"

View File

@ -12,6 +12,7 @@ use crate::{
}; };
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
use tauri_utils::{config::WindowConfig, Theme}; use tauri_utils::{config::WindowConfig, Theme};
use url::Url;
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
@ -226,14 +227,17 @@ pub struct PendingWindow<T: UserEvent, R: Runtime<T>> {
/// How to handle IPC calls on the webview window. /// How to handle IPC calls on the webview window.
pub ipc_handler: Option<WebviewIpcHandler<T, R>>, pub ipc_handler: Option<WebviewIpcHandler<T, R>>,
/// The resolved URL to load on the webview.
pub url: String,
/// Maps runtime id to a string menu id. /// Maps runtime id to a string menu id.
pub menu_ids: Arc<Mutex<HashMap<MenuHash, MenuId>>>, pub menu_ids: Arc<Mutex<HashMap<MenuHash, MenuId>>>,
/// A HashMap mapping JS event names with associated listener ids. /// A HashMap mapping JS event names with associated listener ids.
pub js_event_listeners: Arc<Mutex<HashMap<JsEventListenerKey, HashSet<u64>>>>, pub js_event_listeners: Arc<Mutex<HashMap<JsEventListenerKey, HashSet<u64>>>>,
/// A handler to decide if incoming url is allowed to navigate.
pub navigation_handler: Option<Box<dyn Fn(Url) -> bool + Send>>,
/// The current webview URL.
pub current_url: Arc<Mutex<Url>>,
} }
pub fn is_label_valid(label: &str) -> bool { pub fn is_label_valid(label: &str) -> bool {
@ -270,9 +274,10 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
uri_scheme_protocols: Default::default(), uri_scheme_protocols: Default::default(),
label, label,
ipc_handler: None, ipc_handler: None,
url: "tauri://localhost".to_string(),
menu_ids: Arc::new(Mutex::new(menu_ids)), menu_ids: Arc::new(Mutex::new(menu_ids)),
js_event_listeners: Default::default(), js_event_listeners: Default::default(),
navigation_handler: Default::default(),
current_url: Arc::new(Mutex::new("tauri://localhost".parse().unwrap())),
}) })
} }
} }
@ -299,9 +304,10 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
uri_scheme_protocols: Default::default(), uri_scheme_protocols: Default::default(),
label, label,
ipc_handler: None, ipc_handler: None,
url: "tauri://localhost".to_string(),
menu_ids: Arc::new(Mutex::new(menu_ids)), menu_ids: Arc::new(Mutex::new(menu_ids)),
js_event_listeners: Default::default(), js_event_listeners: Default::default(),
navigation_handler: Default::default(),
current_url: Arc::new(Mutex::new("tauri://localhost".parse().unwrap())),
}) })
} }
} }
@ -342,6 +348,9 @@ pub struct JsEventListenerKey {
/// A webview window that is not yet managed by Tauri. /// A webview window that is not yet managed by Tauri.
#[derive(Debug)] #[derive(Debug)]
pub struct DetachedWindow<T: UserEvent, R: Runtime<T>> { pub struct DetachedWindow<T: UserEvent, R: Runtime<T>> {
/// The current webview URL.
pub current_url: Arc<Mutex<Url>>,
/// Name of the window /// Name of the window
pub label: String, pub label: String,
@ -358,6 +367,7 @@ pub struct DetachedWindow<T: UserEvent, R: Runtime<T>> {
impl<T: UserEvent, R: Runtime<T>> Clone for DetachedWindow<T, R> { impl<T: UserEvent, R: Runtime<T>> Clone for DetachedWindow<T, R> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
current_url: self.current_url.clone(),
label: self.label.clone(), label: self.label.clone(),
dispatcher: self.dispatcher.clone(), dispatcher: self.dispatcher.clone(),
menu_ids: self.menu_ids.clone(), menu_ids: self.menu_ids.clone(),

View File

@ -902,7 +902,7 @@ impl<R: Runtime> Builder<R> {
#[cfg(any(windows, target_os = "linux"))] #[cfg(any(windows, target_os = "linux"))]
runtime_any_thread: false, runtime_any_thread: false,
setup: Box::new(|_| Ok(())), setup: Box::new(|_| Ok(())),
invoke_handler: Box::new(|_| ()), invoke_handler: Box::new(|invoke| invoke.resolver.reject("not implemented")),
invoke_responder: Arc::new(window_invoke_responder), invoke_responder: Arc::new(window_invoke_responder),
invoke_initialization_script: invoke_initialization_script:
"Object.defineProperty(window, '__TAURI_POST_MESSAGE__', { value: (message) => window.ipc.postMessage(JSON.stringify(message)) })".into(), "Object.defineProperty(window, '__TAURI_POST_MESSAGE__', { value: (message) => window.ipc.postMessage(JSON.stringify(message)) })".into(),

View File

@ -25,10 +25,9 @@ use tauri_utils::{
html::{SCRIPT_NONCE_TOKEN, STYLE_NONCE_TOKEN}, html::{SCRIPT_NONCE_TOKEN, STYLE_NONCE_TOKEN},
}; };
use crate::hooks::IpcJavascript;
#[cfg(feature = "isolation")] #[cfg(feature = "isolation")]
use crate::hooks::IsolationJavascript; use crate::hooks::IsolationJavascript;
use crate::pattern::{format_real_schema, PatternJavascript}; use crate::pattern::PatternJavascript;
use crate::{ use crate::{
app::{AppHandle, GlobalWindowEvent, GlobalWindowEventListener}, app::{AppHandle, GlobalWindowEvent, GlobalWindowEventListener},
event::{assert_event_name_is_valid, Event, EventHandler, Listeners}, event::{assert_event_name_is_valid, Event, EventHandler, Listeners},
@ -54,6 +53,7 @@ use crate::{
app::{GlobalMenuEventListener, WindowMenuEvent}, app::{GlobalMenuEventListener, WindowMenuEvent},
window::WebResourceRequestHandler, window::WebResourceRequestHandler,
}; };
use crate::{hooks::IpcJavascript, pattern::format_real_schema};
#[cfg(any(target_os = "linux", target_os = "windows"))] #[cfg(any(target_os = "linux", target_os = "windows"))]
use crate::api::path::{resolve_path, BaseDirectory}; use crate::api::path::{resolve_path, BaseDirectory};
@ -136,7 +136,7 @@ fn set_csp<R: Runtime>(
let default_src = csp let default_src = csp
.entry("default-src".into()) .entry("default-src".into())
.or_insert_with(Default::default); .or_insert_with(Default::default);
default_src.push(format_real_schema(schema)); default_src.push(crate::pattern::format_real_schema(schema));
} }
Csp::DirectiveMap(csp).to_string() Csp::DirectiveMap(csp).to_string()
@ -225,7 +225,7 @@ pub struct InnerWindowManager<R: Runtime> {
/// The script that initializes the invoke system. /// The script that initializes the invoke system.
invoke_initialization_script: String, invoke_initialization_script: String,
/// Application pattern. /// Application pattern.
pattern: Pattern, pub(crate) pattern: Pattern,
} }
impl<R: Runtime> fmt::Debug for InnerWindowManager<R> { impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
@ -357,9 +357,12 @@ impl<R: Runtime> WindowManager<R> {
/// Get the base URL to use for webview requests. /// Get the base URL to use for webview requests.
/// ///
/// In dev mode, this will be based on the `devPath` configuration value. /// In dev mode, this will be based on the `devPath` configuration value.
fn get_url(&self) -> Cow<'_, Url> { pub(crate) fn get_url(&self) -> Cow<'_, Url> {
match self.base_path() { match self.base_path() {
AppUrl::Url(WindowUrl::External(url)) => Cow::Borrowed(url), AppUrl::Url(WindowUrl::External(url)) => Cow::Borrowed(url),
#[cfg(windows)]
_ => Cow::Owned(Url::parse("https://tauri.localhost").unwrap()),
#[cfg(not(windows))]
_ => Cow::Owned(Url::parse("tauri://localhost").unwrap()), _ => Cow::Owned(Url::parse("tauri://localhost").unwrap()),
} }
} }
@ -467,7 +470,7 @@ impl<R: Runtime> WindowManager<R> {
}); });
} }
let window_url = Url::parse(&pending.url).unwrap(); let window_url = pending.current_url.lock().unwrap().clone();
let window_origin = let window_origin =
if cfg!(windows) && window_url.scheme() != "http" && window_url.scheme() != "https" { if cfg!(windows) && window_url.scheme() != "http" && window_url.scheme() != "https" {
format!("https://{}.localhost", window_url.scheme()) format!("https://{}.localhost", window_url.scheme())
@ -1001,7 +1004,16 @@ mod test {
); );
#[cfg(custom_protocol)] #[cfg(custom_protocol)]
assert_eq!(manager.get_url().to_string(), "tauri://localhost"); {
assert_eq!(
manager.get_url().to_string(),
if cfg!(windows) {
"https://tauri.localhost/"
} else {
"tauri://localhost"
}
);
}
#[cfg(dev)] #[cfg(dev)]
assert_eq!(manager.get_url().to_string(), "http://localhost:4000/"); assert_eq!(manager.get_url().to_string(), "http://localhost:4000/");
@ -1052,27 +1064,21 @@ impl<R: Runtime> WindowManager<R> {
return Err(crate::Error::WindowLabelAlreadyExists(pending.label)); return Err(crate::Error::WindowLabelAlreadyExists(pending.label));
} }
#[allow(unused_mut)] // mut url only for the data-url parsing #[allow(unused_mut)] // mut url only for the data-url parsing
let (is_local, mut url) = match &pending.webview_attributes.url { let mut url = match &pending.webview_attributes.url {
WindowUrl::App(path) => { WindowUrl::App(path) => {
let url = self.get_url(); let url = self.get_url();
( // ignore "index.html" just to simplify the url
true, if path.to_str() != Some("index.html") {
// ignore "index.html" just to simplify the url url
if path.to_str() != Some("index.html") { .join(&*path.to_string_lossy())
url .map_err(crate::Error::InvalidUrl)
.join(&*path.to_string_lossy()) // this will never fail
.map_err(crate::Error::InvalidUrl) .unwrap()
// this will never fail } else {
.unwrap() url.into_owned()
} else { }
url.into_owned()
},
)
}
WindowUrl::External(url) => {
let config_url = self.get_url();
(config_url.make_relative(url).is_some(), url.clone())
} }
WindowUrl::External(url) => url.clone(),
_ => unimplemented!(), _ => unimplemented!(),
}; };
@ -1099,7 +1105,7 @@ impl<R: Runtime> WindowManager<R> {
} }
} }
pending.url = url.to_string(); *pending.current_url.lock().unwrap() = url;
if !pending.window_builder.has_icon() { if !pending.window_builder.has_icon() {
if let Some(default_window_icon) = self.inner.default_window_icon.clone() { if let Some(default_window_icon) = self.inner.default_window_icon.clone() {
@ -1115,17 +1121,15 @@ impl<R: Runtime> WindowManager<R> {
} }
} }
if is_local { let label = pending.label.clone();
let label = pending.label.clone(); pending = self.prepare_pending_window(
pending = self.prepare_pending_window( pending,
pending, &label,
&label, window_labels,
window_labels, app_handle.clone(),
app_handle.clone(), web_resource_request_handler,
web_resource_request_handler, )?;
)?; pending.ipc_handler = Some(self.prepare_ipc_handler(app_handle));
pending.ipc_handler = Some(self.prepare_ipc_handler(app_handle));
}
// in `Windows`, we need to force a data_directory // in `Windows`, we need to force a data_directory
// but we do respect user-specification // but we do respect user-specification
@ -1150,6 +1154,17 @@ impl<R: Runtime> WindowManager<R> {
} }
} }
let current_url_ = pending.current_url.clone();
let navigation_handler = pending.navigation_handler.take();
pending.navigation_handler = Some(Box::new(move |url| {
*current_url_.lock().unwrap() = url.clone();
if let Some(handler) = &navigation_handler {
handler(url)
} else {
true
}
}));
Ok(pending) Ok(pending)
} }

View File

@ -11,6 +11,9 @@ use serialize_to_javascript::{default_template, Template};
use tauri_utils::assets::{Assets, EmbeddedAssets}; use tauri_utils::assets::{Assets, EmbeddedAssets};
/// The domain of the isolation iframe source.
pub const ISOLATION_IFRAME_SRC_DOMAIN: &str = "localhost";
/// An application pattern. /// An application pattern.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Pattern<A: Assets = EmbeddedAssets> { pub enum Pattern<A: Assets = EmbeddedAssets> {
@ -87,8 +90,8 @@ pub(crate) struct PatternJavascript {
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn format_real_schema(schema: &str) -> String { pub(crate) fn format_real_schema(schema: &str) -> String {
if cfg!(windows) { if cfg!(windows) {
format!("https://{}.localhost", schema) format!("https://{schema}.{ISOLATION_IFRAME_SRC_DOMAIN}")
} else { } else {
format!("{}://localhost", schema) format!("{schema}://{ISOLATION_IFRAME_SRC_DOMAIN}")
} }
} }

View File

@ -67,6 +67,7 @@ impl<T: UserEvent> RuntimeHandle<T> for MockRuntimeHandle {
) -> Result<DetachedWindow<T, Self::Runtime>> { ) -> Result<DetachedWindow<T, Self::Runtime>> {
Ok(DetachedWindow { Ok(DetachedWindow {
label: pending.label, label: pending.label,
current_url: Arc::new(Mutex::new("tauri://localhost".parse().unwrap())),
dispatcher: MockDispatcher { dispatcher: MockDispatcher {
context: self.context.clone(), context: self.context.clone(),
}, },
@ -616,6 +617,7 @@ impl<T: UserEvent> Runtime<T> for MockRuntime {
fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>> { fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>> {
Ok(DetachedWindow { Ok(DetachedWindow {
label: pending.label, label: pending.label,
current_url: Arc::new(Mutex::new("tauri://localhost".parse().unwrap())),
dispatcher: MockDispatcher { dispatcher: MockDispatcher {
context: self.context.clone(), context: self.context.clone(),
}, },

View File

@ -33,6 +33,7 @@ use crate::{
}; };
use serde::Serialize; use serde::Serialize;
use url::Url;
#[cfg(windows)] #[cfg(windows)]
use windows::Win32::Foundation::HWND; use windows::Win32::Foundation::HWND;
@ -483,7 +484,7 @@ impl<'a, R: Runtime> WindowBuilder<'a, R> {
#[derive(Debug)] #[derive(Debug)]
pub struct Window<R: Runtime> { pub struct Window<R: Runtime> {
/// The webview window created by the runtime. /// The webview window created by the runtime.
window: DetachedWindow<EventLoopMessage, R>, pub(crate) window: DetachedWindow<EventLoopMessage, R>,
/// The manager to associate this webview window with. /// The manager to associate this webview window with.
manager: WindowManager<R>, manager: WindowManager<R>,
pub(crate) app_handle: AppHandle<R>, pub(crate) app_handle: AppHandle<R>,
@ -1157,9 +1158,18 @@ impl<R: Runtime> Window<R> {
/// Webview APIs. /// Webview APIs.
impl<R: Runtime> Window<R> { impl<R: Runtime> Window<R> {
/// Returns the current url of the webview.
pub fn url(&self) -> Url {
self.window.current_url.lock().unwrap().clone()
}
/// Handles this window receiving an [`InvokeMessage`]. /// Handles this window receiving an [`InvokeMessage`].
pub fn on_message(self, payload: InvokePayload) -> crate::Result<()> { pub fn on_message(self, payload: InvokePayload) -> crate::Result<()> {
let manager = self.manager.clone(); let manager = self.manager.clone();
let current_url = self.url();
let config_url = manager.get_url();
let is_local = config_url.make_relative(&current_url).is_some();
match payload.cmd.as_str() { match payload.cmd.as_str() {
"__initialized" => { "__initialized" => {
let payload: PageLoadPayload = serde_json::from_value(payload.inner)?; let payload: PageLoadPayload = serde_json::from_value(payload.inner)?;
@ -1173,8 +1183,15 @@ impl<R: Runtime> Window<R> {
payload.inner, payload.inner,
); );
let resolver = InvokeResolver::new(self, payload.callback, payload.error); let resolver = InvokeResolver::new(self, payload.callback, payload.error);
let invoke = Invoke { message, resolver }; let invoke = Invoke { message, resolver };
if !is_local {
invoke
.resolver
.reject("Remote URLs are not allowed to access the IPC");
return Ok(());
}
if let Some(module) = &payload.tauri_module { if let Some(module) = &payload.tauri_module {
crate::endpoints::handle( crate::endpoints::handle(
module.to_string(), module.to_string(),

View File

@ -3132,7 +3132,7 @@ dependencies = [
[[package]] [[package]]
name = "tauri" name = "tauri"
version = "1.0.2" version = "1.0.8"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"attohttpc", "attohttpc",
@ -3194,7 +3194,7 @@ dependencies = [
[[package]] [[package]]
name = "tauri-build" name = "tauri-build"
version = "1.0.2" version = "1.0.4"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cargo_toml", "cargo_toml",
@ -3209,7 +3209,7 @@ dependencies = [
[[package]] [[package]]
name = "tauri-codegen" name = "tauri-codegen"
version = "1.0.2" version = "1.0.4"
dependencies = [ dependencies = [
"base64", "base64",
"brotli", "brotli",
@ -3233,7 +3233,7 @@ dependencies = [
[[package]] [[package]]
name = "tauri-macros" name = "tauri-macros"
version = "1.0.2" version = "1.0.4"
dependencies = [ dependencies = [
"heck 0.4.0", "heck 0.4.0",
"proc-macro2", "proc-macro2",
@ -3245,7 +3245,7 @@ dependencies = [
[[package]] [[package]]
name = "tauri-runtime" name = "tauri-runtime"
version = "0.10.1" version = "0.10.2"
dependencies = [ dependencies = [
"gtk", "gtk",
"http", "http",
@ -3256,6 +3256,7 @@ dependencies = [
"serde_json", "serde_json",
"tauri-utils", "tauri-utils",
"thiserror", "thiserror",
"url",
"uuid 1.1.2", "uuid 1.1.2",
"webview2-com", "webview2-com",
"windows 0.37.0", "windows 0.37.0",
@ -3263,7 +3264,7 @@ dependencies = [
[[package]] [[package]]
name = "tauri-runtime-wry" name = "tauri-runtime-wry"
version = "0.10.1" version = "0.10.2"
dependencies = [ dependencies = [
"cocoa", "cocoa",
"gtk", "gtk",
@ -3272,6 +3273,7 @@ dependencies = [
"raw-window-handle", "raw-window-handle",
"tauri-runtime", "tauri-runtime",
"tauri-utils", "tauri-utils",
"url",
"uuid 1.1.2", "uuid 1.1.2",
"webkit2gtk", "webkit2gtk",
"webview2-com", "webview2-com",
@ -3281,7 +3283,7 @@ dependencies = [
[[package]] [[package]]
name = "tauri-utils" name = "tauri-utils"
version = "1.0.2" version = "1.0.3"
dependencies = [ dependencies = [
"aes-gcm", "aes-gcm",
"brotli", "brotli",