Run notification click actions as argv, not shell strings
The click action of a notification was a free-form shell string run through `bash -lc`, safe only when every sender shell-quoted every interpolated value perfectly. One slip is RCE: a hostile yt-dlp video title forged an output record and injected an mpv option into the click command (mehmetince.net RCE, partially addressed by #7847). Add a parameterized transport: omarchy-notification-send gains --exec-arg (repeatable), encoding a JSON argv into the omarchy-exec-argv hint. The shell runs it with Quickshell.execDetached(argv) and no shell, so data an attacker controls is only ever one argument and can never be reparsed as a command. The shell fails closed on a malformed argv hint. The legacy free-form --exec string is retained but honored only from Omarchy's own omarchy-action toasts, and deprecated. Migrate all in-repo callers (screenshot, screen recording, taildrop receive, migrate-notify, crash-watch, yt-dlp host) to --exec-arg. Update docs and tests.
This commit is contained in:
@@ -70,10 +70,10 @@ title_from_file() {
|
||||
fi
|
||||
}
|
||||
|
||||
# `--` keeps a path that starts with `-` from being parsed as an mpv option.
|
||||
playback_command() {
|
||||
printf 'mpv -- %q' "$1"
|
||||
}
|
||||
# The click action is passed to the shell as an argv vector (--exec-arg), so the
|
||||
# path is one literal argument and never reaches a shell. `--` still guards mpv
|
||||
# itself against parsing a leading-dash filename as an option.
|
||||
playback_exec_args=(--exec-arg mpv --exec-arg -- --exec-arg)
|
||||
|
||||
# Drive the Quickshell OSD — a single overlay that updates in place (like the
|
||||
# volume/brightness bar), so download progress never stacks like notifications.
|
||||
@@ -153,7 +153,7 @@ download_url() {
|
||||
# toast would exit before the thumbnail cleanup below is ever scheduled.
|
||||
omarchy-notification-send -g "Download complete" "$title" \
|
||||
-t 10000 --image "${preview:-$filepath}" \
|
||||
--exec "$(playback_command "$filepath")" || true
|
||||
"${playback_exec_args[@]}" "$filepath" || true
|
||||
|
||||
# The shell loads the thumbnail into memory when the toast appears and never
|
||||
# re-reads the file, so the preview only has to outlive that load, not the
|
||||
|
||||
Reference in New Issue
Block a user