Shell-quote bind_command args (Hyprland exec_cmd injection)
fix(hypr): Grok-flagged security finding: shell_single was applied to bin and sock but args was interpolated raw. A profile hotkey containing shell metacharacters could become a Hyprland exec_cmd injection. - src/hypr.rs: bind_command now wraps args in shell_single - New tests: - bind_command_quotes_args_with_metacharacters - shell_single_handles_inner_quote - Doc comment updated to name the threat and what gets escaped 93+/0 cargo test; clippy clean.
This commit is contained in:
parent
8eb5346d92
commit
20f0160799
24
src/hypr.rs
24
src/hypr.rs
@ -227,12 +227,15 @@ fn shell_single(s: &str) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Hyprland exec_cmd string. `args` is the IPC line after the binary, e.g. `hotkey Alt+G`.
|
/// Hyprland exec_cmd string. `args` is the IPC line after the binary, e.g. `hotkey Alt+G`.
|
||||||
|
/// `bin`, `sock`, and `args` are all single-quoted so a map hotkey containing
|
||||||
|
/// shell metacharacters (`;`, backticks, `$()`, quotes, spaces) cannot inject
|
||||||
|
/// into the compositor's `exec_cmd`.
|
||||||
pub fn bind_command(bin: &str, sock: &str, args: &str) -> String {
|
pub fn bind_command(bin: &str, sock: &str, args: &str) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{} ipc --sock {} {}",
|
"{} ipc --sock {} {}",
|
||||||
shell_single(bin),
|
shell_single(bin),
|
||||||
shell_single(sock),
|
shell_single(sock),
|
||||||
args
|
shell_single(args)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,15 +315,30 @@ where
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::bind_command;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bind_command_has_one_ipc() {
|
fn bind_command_has_one_ipc() {
|
||||||
let cmd = bind_command("/tmp/enboxer", "/tmp/enboxer.sock", "hotkey Alt+G");
|
let cmd = bind_command("/tmp/enboxer", "/tmp/enboxer.sock", "hotkey Alt+G");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cmd,
|
cmd,
|
||||||
"'/tmp/enboxer' ipc --sock '/tmp/enboxer.sock' hotkey Alt+G"
|
"'/tmp/enboxer' ipc --sock '/tmp/enboxer.sock' 'hotkey Alt+G'"
|
||||||
);
|
);
|
||||||
assert_eq!(cmd.matches(" ipc ").count(), 1);
|
assert_eq!(cmd.matches(" ipc ").count(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bind_command_quotes_args_with_metacharacters() {
|
||||||
|
// shell_single must escape a hostile arg (semicolon, backtick,
|
||||||
|
// dollar-paren) so it cannot inject into Hyprland's exec_cmd.
|
||||||
|
let s = bind_command(
|
||||||
|
"enboxer",
|
||||||
|
"/tmp/enboxer.sock",
|
||||||
|
"hotkey Alt+G; cat /etc/passwd",
|
||||||
|
);
|
||||||
|
assert!(s.starts_with("'enboxer' ipc --sock '/tmp/enboxer.sock' "));
|
||||||
|
assert!(s.contains("'hotkey Alt+G; cat /etc/passwd'"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user