diff --git a/permissions/autogenerated/reference.md b/permissions/autogenerated/reference.md index 602814f..d2b86f8 100644 --- a/permissions/autogenerated/reference.md +++ b/permissions/autogenerated/reference.md @@ -5,7 +5,7 @@ shell functionality is exposed by default. #### Granted Permissions -It allows to use the `open` functionality without any specific +It allows to use the `open` functionality with a reasonable scope pre-configured. It will allow opening `http(s)://`, `tel:` and `mailto:` links. diff --git a/permissions/default.toml b/permissions/default.toml index 4569b05..dba2ea2 100644 --- a/permissions/default.toml +++ b/permissions/default.toml @@ -7,7 +7,7 @@ shell functionality is exposed by default. #### Granted Permissions -It allows to use the `open` functionality without any specific +It allows to use the `open` functionality with a reasonable scope pre-configured. It will allow opening `http(s)://`, `tel:` and `mailto:` links. """ diff --git a/permissions/schemas/schema.json b/permissions/schemas/schema.json index b729595..f8127c5 100644 --- a/permissions/schemas/schema.json +++ b/permissions/schemas/schema.json @@ -355,7 +355,7 @@ "markdownDescription": "Denies the stdin_write command without any pre-configured scope." }, { - "description": "This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality without any specific\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n\n#### This default permission set includes:\n\n- `allow-open`", + "description": "This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n", "type": "string", "const": "default", "markdownDescription": "This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality without any specific\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n\n#### This default permission set includes:\n\n- `allow-open`" diff --git a/src/commands.rs b/src/commands.rs index 5bee6b9..5275e9b 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -311,5 +311,5 @@ pub async fn open( path: String, with: Option, ) -> crate::Result<()> { - shell.open(path, with) + crate::open::open(Some(&shell.open_scope), path, with) } diff --git a/src/config.rs b/src/config.rs index cad267a..69a92ee 100644 --- a/src/config.rs +++ b/src/config.rs @@ -18,6 +18,9 @@ pub struct Config { #[serde(untagged, deny_unknown_fields)] #[non_exhaustive] pub enum ShellAllowlistOpen { + /// Shell open API allowlist is not defined by the user. + /// In this case we add the default validation regex (same as [`Self::Flag(true)`]). + Unset, /// If the shell open API should be enabled. /// /// If enabled, the default validation regex (`^((mailto:\w+)|(tel:\w+)|(https?://\w+)).+`) is used. @@ -35,6 +38,6 @@ pub enum ShellAllowlistOpen { impl Default for ShellAllowlistOpen { fn default() -> Self { - Self::Flag(false) + Self::Unset } } diff --git a/src/lib.rs b/src/lib.rs index 3dffc50..c950373 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,7 +75,7 @@ impl Shell { #[deprecated(since = "2.1.0", note = "Use tauri-plugin-opener instead.")] #[allow(deprecated)] pub fn open(&self, path: impl Into, with: Option) -> Result<()> { - open::open(&self.open_scope, path.into(), with) + open::open(None, path.into(), with) } /// Open a (url) path with a default or specific browser opening program. @@ -147,7 +147,8 @@ pub fn init() -> TauriPlugin> { fn open_scope(open: &config::ShellAllowlistOpen) -> scope::OpenScope { let shell_scope_open = match open { config::ShellAllowlistOpen::Flag(false) => None, - config::ShellAllowlistOpen::Flag(true) => { + // we want to add a basic regex validation even if the config is not set + config::ShellAllowlistOpen::Unset | config::ShellAllowlistOpen::Flag(true) => { Some(Regex::new(r"^((mailto:\w+)|(tel:\w+)|(https?://\w+)).+").unwrap()) } config::ShellAllowlistOpen::Validate(validator) => { diff --git a/src/open.rs b/src/open.rs index fe22470..6958a83 100644 --- a/src/open.rs +++ b/src/open.rs @@ -119,6 +119,20 @@ impl Program { /// }); /// ``` #[deprecated(since = "2.1.0", note = "Use tauri-plugin-opener instead.")] -pub fn open>(scope: &OpenScope, path: P, with: Option) -> crate::Result<()> { - scope.open(path.as_ref(), with).map_err(Into::into) +pub fn open>( + scope: Option<&OpenScope>, + path: P, + with: Option, +) -> crate::Result<()> { + // validate scope if we have any (JS calls) + if let Some(scope) = scope { + scope.open(path.as_ref(), with).map_err(Into::into) + } else { + // when running directly from Rust code we don't need to validate the path + match with.map(Program::name) { + Some(program) => ::open::with_detached(path.as_ref(), program), + None => ::open::that_detached(path.as_ref()), + } + .map_err(Into::into) + } } diff --git a/src/scope.rs b/src/scope.rs index d46bfa2..3a450af 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -142,6 +142,7 @@ impl ScopeAllowedArg { /// Scope for the open command pub struct OpenScope { /// The validation regex that `shell > open` paths must match against. + /// When set to `None`, no values are accepted. pub open: Option, } @@ -212,6 +213,12 @@ impl OpenScope { validation: regex.as_str().into(), }); } + } else { + log::warn!("open() command called but the plugin configuration denies calls from JavaScript; set `tauri.conf.json > plugins > shell > open` to true or a validation regex string"); + return Err(Error::Validation { + index: 0, + validation: "tauri^".to_string(), // purposefully impossible regex + }); } // The prevention of argument escaping is handled by the usage of std::process::Command::arg by