fix(acl): inconsistencies on urlpattern usage for remote domain URL (#9133)

* fix(acl): inconsistencies on urlpattern usage for remote domain URL

* remove println!

* typo

* fix tests
This commit is contained in:
Lucas Fernandes Nogueira 2024-03-11 13:39:17 -03:00 committed by GitHub
parent 490a6b424e
commit e673854c83
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 120 additions and 35 deletions

View File

@ -0,0 +1,5 @@
---
"tauri": patch:bug
---
Fixes capability remote domain not allowing subpaths, query parameters and hash when those values are empty.

View File

@ -1141,7 +1141,7 @@
],
"properties": {
"urls": {
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).",
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n# Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api",
"type": "array",
"items": {
"type": "string"

View File

@ -90,6 +90,11 @@ fn default_capability_local() -> bool {
#[serde(rename_all = "camelCase")]
pub struct CapabilityRemote {
/// Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).
///
/// # Examples
///
/// - "https://*.mydomain.dev": allows subdomains of mydomain.dev
/// - "https://mydomain.dev/api/*": allows any subpath of mydomain.dev/api
pub urls: Vec<String>,
}

View File

@ -202,7 +202,21 @@ impl FromStr for RemoteUrlPattern {
type Err = urlpattern::quirks::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let init = urlpattern::UrlPatternInit::parse_constructor_string::<regex::Regex>(s, None)?;
let mut init = urlpattern::UrlPatternInit::parse_constructor_string::<regex::Regex>(s, None)?;
if init.search.as_ref().map(|p| p.is_empty()).unwrap_or(true) {
init.search.replace("*".to_string());
}
if init.hash.as_ref().map(|p| p.is_empty()).unwrap_or(true) {
init.hash.replace("*".to_string());
}
if init
.pathname
.as_ref()
.map(|p| p.is_empty() || p == "/")
.unwrap_or(true)
{
init.pathname.replace("*".to_string());
}
let pattern = urlpattern::UrlPattern::parse(init)?;
Ok(Self(Arc::new(pattern), s.to_string()))
}
@ -251,6 +265,46 @@ pub enum ExecutionContext {
},
}
#[cfg(test)]
mod tests {
use crate::acl::RemoteUrlPattern;
#[test]
fn url_pattern_domain_wildcard() {
let pattern: RemoteUrlPattern = "http://*".parse().unwrap();
assert!(pattern.test(&"http://tauri.app/path".parse().unwrap()));
assert!(pattern.test(&"http://tauri.app/path?q=1".parse().unwrap()));
assert!(pattern.test(&"http://localhost/path".parse().unwrap()));
assert!(pattern.test(&"http://localhost/path?q=1".parse().unwrap()));
let pattern: RemoteUrlPattern = "http://*.tauri.app".parse().unwrap();
assert!(!pattern.test(&"http://tauri.app/path".parse().unwrap()));
assert!(!pattern.test(&"http://tauri.app/path?q=1".parse().unwrap()));
assert!(pattern.test(&"http://api.tauri.app/path".parse().unwrap()));
assert!(pattern.test(&"http://api.tauri.app/path?q=1".parse().unwrap()));
assert!(!pattern.test(&"http://localhost/path".parse().unwrap()));
assert!(!pattern.test(&"http://localhost/path?q=1".parse().unwrap()));
}
#[test]
fn url_pattern_path_wildcard() {
let pattern: RemoteUrlPattern = "http://localhost/*".parse().unwrap();
assert!(pattern.test(&"http://localhost/path".parse().unwrap()));
assert!(pattern.test(&"http://localhost/path?q=1".parse().unwrap()));
}
#[test]
fn url_pattern_scheme_wildcard() {
let pattern: RemoteUrlPattern = "*://localhost".parse().unwrap();
assert!(pattern.test(&"http://localhost/path".parse().unwrap()));
assert!(pattern.test(&"https://localhost/path?q=1".parse().unwrap()));
assert!(pattern.test(&"custom://localhost/path".parse().unwrap()));
}
}
#[cfg(feature = "build")]
mod build_ {
use std::convert::identity;

View File

@ -90,50 +90,59 @@ Resolved {
},
},
pathname: Component {
pattern_string: "/",
pattern_string: "*",
regexp: Ok(
Regex(
"^/$",
"^(.*)$",
),
),
group_name_list: [],
group_name_list: [
"0",
],
matcher: Matcher {
prefix: "",
suffix: "",
inner: Literal {
literal: "/",
inner: SingleCapture {
filter: None,
allow_empty: true,
},
},
},
search: Component {
pattern_string: "",
pattern_string: "*",
regexp: Ok(
Regex(
"^$",
"^(.*)$",
),
),
group_name_list: [],
group_name_list: [
"0",
],
matcher: Matcher {
prefix: "",
suffix: "",
inner: Literal {
literal: "",
inner: SingleCapture {
filter: None,
allow_empty: true,
},
},
},
hash: Component {
pattern_string: "",
pattern_string: "*",
regexp: Ok(
Regex(
"^$",
"^(.*)$",
),
),
group_name_list: [],
group_name_list: [
"0",
],
matcher: Matcher {
prefix: "",
suffix: "",
inner: Literal {
literal: "",
inner: SingleCapture {
filter: None,
allow_empty: true,
},
},
},
@ -251,50 +260,59 @@ Resolved {
},
},
pathname: Component {
pattern_string: "/",
pattern_string: "*",
regexp: Ok(
Regex(
"^/$",
"^(.*)$",
),
),
group_name_list: [],
group_name_list: [
"0",
],
matcher: Matcher {
prefix: "",
suffix: "",
inner: Literal {
literal: "/",
inner: SingleCapture {
filter: None,
allow_empty: true,
},
},
},
search: Component {
pattern_string: "",
pattern_string: "*",
regexp: Ok(
Regex(
"^$",
"^(.*)$",
),
),
group_name_list: [],
group_name_list: [
"0",
],
matcher: Matcher {
prefix: "",
suffix: "",
inner: Literal {
literal: "",
inner: SingleCapture {
filter: None,
allow_empty: true,
},
},
},
hash: Component {
pattern_string: "",
pattern_string: "*",
regexp: Ok(
Regex(
"^$",
"^(.*)$",
),
),
group_name_list: [],
group_name_list: [
"0",
],
matcher: Matcher {
prefix: "",
suffix: "",
inner: Literal {
literal: "",
inner: SingleCapture {
filter: None,
allow_empty: true,
},
},
},

View File

@ -2,7 +2,10 @@
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "run-app",
"description": "permissions to run the app",
"windows": ["main", "main-*"],
"windows": [
"main",
"main-*"
],
"permissions": [
{
"identifier": "allow-log-operation",
@ -96,4 +99,4 @@
"tray:allow-set-icon-as-template",
"tray:allow-set-show-menu-on-left-click"
]
}
}

View File

@ -1141,7 +1141,7 @@
],
"properties": {
"urls": {
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).",
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n# Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api",
"type": "array",
"items": {
"type": "string"