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.
Quickshell.execDetached(argv) ran the click target with only the shell
process's stripped environment, so GUI actions like the screenshot editor
(tensaku-edit) — resolved on the login-shell PATH the old `bash -lc` string
exec provided — stopped launching on click.
Run the argv through `bash -lc 'exec "$@"'` instead: the script text is a
constant and the arguments are passed as positional parameters, which bash
expands without re-tokenizing or re-evaluating, so injection safety is intact
while PATH and session env match the old behavior exactly.
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.
* Show OSD and sync touchpad steps when scrolling bar widgets
Scrolling the volume or brightness icon in the bar changed the value
directly without ever calling omarchy-osd, so only the keyboard media
keys showed the popup. On top of that, a touchpad's stream of many
small wheel events per finger-drag wasn't matched to a mouse's single
±120 notch per click, so touchpad scrolling felt uncoordinated and
uneven next to the keyboard/mouse behavior.
- shell/plugins/panels/audio/Panel.qml: accumulate raw wheel delta and
only apply a step once it crosses a full mouse-notch's worth, so
touchpad and mouse move the volume in identical 5% increments, and
ping the OSD each time a step actually lands.
- shell/plugins/panels/monitor/Panel.qml: same accumulator for
brightness, with a 5% floor so scrolling down can never blank the
screen.
- shell/plugins/osd/Osd.qml: animate the progress bar's width instead
of snapping, so successive steps glide smoothly.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Fix bar wheel OSD behavior
* Normalize scaled wheel events
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
* emoji panel: handle CTRL+BACKSPACE to clear filter
* shell: handle CTRL+BACKSPACE to clear filter in all search overlays
* Indentation fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* menu filters: align keyboard editing with Qt standard shortcuts
* menu filters: extract shared filter-editing helpers
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* potential fix for pull request findings
* Only treat filter edit keys as edits when they change the text
Backspace/Ctrl+U on an empty filter no longer calls setFilter(""),
which was resetting the list selection back to the top. This also lets
the menu's empty-filter Backspace fall through to goBack() with any
modifier held, as it did before the Util extraction.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
With initial workspace tracking disabled, windows naturally open on the active workspace. Remove the explicit Hyprland workspace dispatch and let shell actions, shell restarts, and presentation terminals launch directly.
CustomCommandModule.update() in Bar.qml called root.parseModuleJson(raw)
but the function was removed in 3b970068 (the indicator split). Any
custom command module emitting waybar-style JSON would have crashed on
first poll.
Hoist the helper into Util so both call sites — the bar's custom command
module and BarIndicator.extractData — share one definition.