Skip to content

Commit

Permalink
feat(shell): enhance regex validators to match on entire string (#1603)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog authored Aug 2, 2024
1 parent b1e5cae commit 34df132
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changes/shell-open-regex-match-string.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"shell": patch
---

Change the `open` scope validator regex to match on the entire string.
6 changes: 6 additions & 0 deletions .changes/shell-regex-match-string.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"shell": patch
---

Change the `execute` scope argument validator regex to match on the entire string by default.
If this behavior is not desired check the `raw` boolean configuration option that is available along the `validator` string.
6 changes: 3 additions & 3 deletions examples/api/src-tauri/capabilities/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@
"dialog:allow-confirm",
"dialog:allow-message",
{
"identifier": "shell:allow-execute",
"identifier": "shell:allow-spawn",
"allow": [
{
"name": "sh",
"cmd": "sh",
"args": [
"-c",
{
"validator": "\\S+"
"validator": ".+"
}
]
},
Expand All @@ -54,7 +54,7 @@
"args": [
"/C",
{
"validator": "\\S+"
"validator": ".+"
}
]
}
Expand Down
7 changes: 6 additions & 1 deletion examples/api/src-tauri/gen/schemas/desktop-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -7410,8 +7410,13 @@
"validator"
],
"properties": {
"raw": {
"description": "Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.",
"default": false,
"type": "boolean"
},
"validator": {
"description": "[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\n[regex]: https://docs.rs/regex/latest/regex/#syntax",
"description": "[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: <https://docs.rs/regex/latest/regex/#syntax>",
"type": "string"
}
},
Expand Down
3 changes: 3 additions & 0 deletions plugins/shell/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ pub enum ShellAllowlistOpen {

/// Enable the shell open API, with a custom regex that the opened path must match against.
///
/// The regex string is automatically surrounded by `^...$` to match the full string.
/// For example the `https?://\w+` regex would be registered as `^https?://\w+$`.
///
/// If using a custom regex to support a non-http(s) schema, care should be used to prevent values
/// that allow flag-like strings to pass validation. e.g. `--enable-debugging`, `-i`, `/R`.
Validate(String),
Expand Down
3 changes: 2 additions & 1 deletion plugins/shell/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,9 @@ fn open_scope(open: &config::ShellAllowlistOpen) -> scope::OpenScope {
Some(Regex::new(r"^((mailto:\w+)|(tel:\w+)|(https?://\w+)).+").unwrap())
}
config::ShellAllowlistOpen::Validate(validator) => {
let regex = format!("^{validator}$");
let validator =
Regex::new(validator).unwrap_or_else(|e| panic!("invalid regex {validator}: {e}"));
Regex::new(&regex).unwrap_or_else(|e| panic!("invalid regex {regex}: {e}"));
Some(validator)
}
};
Expand Down
11 changes: 8 additions & 3 deletions plugins/shell/src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,14 @@ impl ScopeObject for ScopeAllowedCommand {
crate::scope_entry::ShellAllowedArg::Fixed(fixed) => {
crate::scope::ScopeAllowedArg::Fixed(fixed)
}
crate::scope_entry::ShellAllowedArg::Var { validator } => {
let validator = Regex::new(&validator)
.unwrap_or_else(|e| panic!("invalid regex {validator}: {e}"));
crate::scope_entry::ShellAllowedArg::Var { validator, raw } => {
let regex = if raw {
validator
} else {
format!("^{validator}$")
};
let validator = Regex::new(&regex)
.unwrap_or_else(|e| panic!("invalid regex {regex}: {e}"));
crate::scope::ScopeAllowedArg::Var { validator }
}
});
Expand Down
13 changes: 12 additions & 1 deletion plugins/shell/src/scope_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,18 @@ pub enum ShellAllowedArg {
/// This will require the argument value passed to this variable to match the `validator` regex
/// before it will be executed.
///
/// [regex]: https://docs.rs/regex/latest/regex/#syntax
/// The regex string is by default surrounded by `^...$` to match the full string.
/// For example the `https?://\w+` regex would be registered as `^https?://\w+$`.
///
/// [regex]: <https://docs.rs/regex/latest/regex/#syntax>
validator: String,

/// Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.
///
/// This means the regex will not match on the entire string by default, which might
/// be exploited if your regex allow unexpected input to be considered valid.
/// When using this option, make sure your regex is correct.
#[serde(default)]
raw: bool,
},
}

0 comments on commit 34df132

Please sign in to comment.