A free-form shell-string --exec sitting next to the safe --exec-arg is a standing invitation for the next caller to interpolate untrusted data and reintroduce the RCE. Remove it: omarchy-notification-send --exec now errors and points at --exec-arg, and the shell drops the omarchy-exec string hint and its bash -lc execution path, leaving only the argv path. Migrate the remaining string callers (the first-run invitation hooks, wifi and welcome prompts) to --exec-arg, and update their notification mocks. Trim the verbose security comments added along the way.
135 lines
3.2 KiB
Bash
Executable File
135 lines
3.2 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Send an Omarchy desktop notification
|
|
# omarchy:args=[--exec-arg <arg>]... [--app-name <app-name>] [-g <glyph>] [-u <low|normal|critical>] [--image <path-or-uri>] <headline> [description] [notify-send options]
|
|
# omarchy:examples=omarchy notification send "Reminder" "5 minutes are up" -g
|
|
|
|
set -euo pipefail
|
|
|
|
headline=""
|
|
description=""
|
|
glyph=
|
|
urgency="low"
|
|
app_name="omarchy-action"
|
|
image=
|
|
exec_args=()
|
|
args=()
|
|
parsed_option_args=0
|
|
|
|
parse_omarchy_option() {
|
|
case $1 in
|
|
-g | --glyph)
|
|
if (($# < 2)); then
|
|
echo "Missing value for $1" >&2
|
|
exit 1
|
|
fi
|
|
glyph=$2
|
|
parsed_option_args=2
|
|
return 0
|
|
;;
|
|
-u | --urgency)
|
|
if (($# < 2)); then
|
|
echo "Missing value for $1" >&2
|
|
exit 1
|
|
fi
|
|
urgency="$2"
|
|
parsed_option_args=2
|
|
return 0
|
|
;;
|
|
--app-name)
|
|
if (($# < 2)); then
|
|
echo "Missing value for $1" >&2
|
|
exit 1
|
|
fi
|
|
app_name=$2
|
|
parsed_option_args=2
|
|
return 0
|
|
;;
|
|
--image)
|
|
if (($# < 2)); then
|
|
echo "Missing value for $1" >&2
|
|
exit 1
|
|
fi
|
|
image=$2
|
|
parsed_option_args=2
|
|
return 0
|
|
;;
|
|
--exec)
|
|
# Removed: a free-form shell string is safe only if the caller quotes every
|
|
# value, and its existence invites the next caller to skip that. Use --exec-arg.
|
|
echo "--exec is no longer supported: pass each argument with --exec-arg (e.g. --exec-arg mpv --exec-arg -- --exec-arg \"\$file\")" >&2
|
|
exit 1
|
|
;;
|
|
--exec-arg)
|
|
if (($# < 2)); then
|
|
echo "Missing value for $1" >&2
|
|
exit 1
|
|
fi
|
|
# One literal argument of the click command, taken verbatim (even a "-value").
|
|
exec_args+=("$2")
|
|
parsed_option_args=2
|
|
return 0
|
|
;;
|
|
esac
|
|
|
|
return 1
|
|
}
|
|
|
|
while (($# > 0)); do
|
|
if parse_omarchy_option "$@"; then
|
|
shift "$parsed_option_args"
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
|
|
if (($# < 1)); then
|
|
echo "Usage: omarchy-notification-send [--exec-arg <arg>]... [--app-name <app-name>] [-g <glyph>] [-u <low|normal|critical>] [--image <path-or-uri>] <headline> [description] [notify-send options]"
|
|
exit 1
|
|
fi
|
|
|
|
headline=$1
|
|
shift
|
|
|
|
if (($# > 0)) && [[ $1 != -* ]]; then
|
|
description=$1
|
|
shift
|
|
fi
|
|
|
|
while (($# > 0)); do
|
|
if parse_omarchy_option "$@"; then
|
|
shift "$parsed_option_args"
|
|
else
|
|
args+=("$1")
|
|
shift
|
|
fi
|
|
done
|
|
|
|
# Tag as a user-action toast so it pops through DND.
|
|
args+=("-a" "$app_name" "-u" "$urgency")
|
|
|
|
if [[ -n $glyph ]]; then
|
|
args+=("--hint=string:omarchy-glyph:$glyph")
|
|
fi
|
|
|
|
if [[ -n $image ]]; then
|
|
args+=("--hint=string:image-path:$image")
|
|
fi
|
|
|
|
# The click command travels with the popup as an argv hint the shell runs
|
|
# itself, so restored toasts stay clickable and senders don't block on a
|
|
# libnotify action (which dies when the shell restarts). --exec-arg is the only
|
|
# form: no free-form shell string to interpolate into unsafely.
|
|
if ((${#exec_args[@]} > 0)); then
|
|
# NUL-delimit into jq so every byte survives as data: jq's own --args would eat
|
|
# a bare "--", and a newline in an arg must not split the vector.
|
|
exec_argv_json=$(printf '%s\0' "${exec_args[@]}" | jq -Rsc 'split("\u0000")[:-1]')
|
|
args+=("--hint=string:omarchy-exec-argv:$exec_argv_json")
|
|
fi
|
|
|
|
if [[ -n $description ]]; then
|
|
notify-send "${args[@]}" "$headline" "$description"
|
|
else
|
|
notify-send "${args[@]}" "$headline"
|
|
fi
|