Skip to content

Refuse hook and state names that are paths - #8170

Open
Adolanium wants to merge 1 commit into
omacom:quattrofrom
Adolanium:hook-state-name-guard
Open

Refuse hook and state names that are paths#8170
Adolanium wants to merge 1 commit into
omacom:quattrofrom
Adolanium:hook-state-name-guard

Conversation

@Adolanium

@Adolanium Adolanium commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

omarchy-hook and omarchy-state set join a name straight into a path without looking at it:

HOOK_PATH="$HOME/.config/omarchy/hooks/$1"
...
bash "$HOOK_PATH" "$@"
set) touch "$STATE_DIR/$STATE_NAME" ;;

On the current code, omarchy-hook ../../evil runs ~/.config/evil, and omarchy-state set ../../escape creates ~/.local/escape. I checked that both happen before this change.

This is a robustness fix, not a security one. Every caller in the repo passes a fixed label: omarchy-update runs omarchy-hook post-update, omarchy-theme-set runs omarchy-hook theme-set "$THEME_NAME" (the theme name is the argument, not the hook name), omarchy-channel-set and the migrations run omarchy-state set reboot-required. No user or network input reaches either command. The guard is there so a future caller that builds a name from something else cannot quietly write or run outside the directory.

What changed:

  • Both commands refuse an empty name, a name with a / in it, or a name that is exactly . or ... They exit 2 and print why on stderr.
  • Nothing else is refused. Once slashes are out, only a whole name of . or .. can leave the directory, so names like a..b or v1..2 stay valid. This matches how omarchy-webapp-install and omarchy-theme-set guard their names.
  • omarchy-state clear is unchanged on purpose. It matches basenames through find -name, so a pattern can never walk out of the directory.

Tests: new test/shell.d/hook-state-name-guard-test.sh, 13 cases. A plain hook still runs, a plain state file is still created, a..b and v1..2 are accepted, . and .. and ../x and sub/dir are refused with nothing created or run outside the directory, and clear still honors glob patterns. Against the code before this change the test stops at the first refusal case. The other hook and state tests (monitor-state-test.sh, nvidia-kms-hook-test.sh) pass unchanged.

Copilot AI balanced review requested due to automatic review settings August 25, 2026 06:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds path-traversal guards for hook and state labels.

Changes:

  • Rejects hook and state names containing / or ...
  • Adds regression coverage for valid names, traversal attempts, and state glob clearing.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Reviewed changes

Copilot reviewed 1 out of 3 changed files in this pull request and generated no comments.

File Description
bin/omarchy-hook Validates hook names before resolving them.
bin/omarchy-state Validates state names before creating files.
test/shell.d/hook-state-name-guard-test.sh Tests accepted and rejected names.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

omarchy-hook and omarchy-state set join a name straight into a path. A name
with a slash, or a bare . or .., points outside the hooks or state directory.
Every caller in the repo passes a fixed label, so this is a footgun guard for
future callers, not a fix for anything that ships today.

Names with dots in the middle (a..b) stay allowed. omarchy-state clear is
untouched: find -name matches basenames only.
@Adolanium
Adolanium force-pushed the hook-state-name-guard branch from 6c9b1b1 to 0a65b45 Compare September 1, 2026 20:22
@Adolanium Adolanium changed the title Refuse hook and state names that point outside their directories Refuse hook and state names that are paths Sep 1, 2026
@Adolanium

Copy link
Copy Markdown
Contributor Author

Reworked this after a second look.

  • The check no longer refuses any .. in a name, which was too broad (it blocked harmless names like a..b). It now refuses only an empty name, a name with a /, or a name that is exactly . or ... Once slashes are out, those are the only names that can leave the directory. Same shape as the guard in omarchy-webapp-install and omarchy-theme-set.
  • Reframed the title, body, and comments. Every caller passes a fixed label, so this is a footgun guard for future callers, not a security fix.
  • Tests grew from 7 to 13 cases: a..b and v1..2 accepted, . and .. refused, ../x and sub/dir still refused.

@ErikMelton

Copy link
Copy Markdown
Member

3 improvements;

Migration can overwrite administrator-authored PAM policy; treats any package-unowned file containing pam_fprintd, the gate, or the FIDO authfile as Omarchy-owned. Custom PAM files commonly satisfy that predicate. The rebuild then discards comments and all custom account, password, and session directives. Match exact known legacy layouts or replace only the known pam_unix lines while preserving everything else.

Post-removal installations remain vulnerable. The same predicate requires a hardware-auth marker, but both removal commands delete those markers while leaving the bare four-line pam_unix override behind. Users who removed fingerprint/FIDO2 before upgrading are therefore skipped permanently. Recognize the exact markerless legacy layout too.

Failed repairs are marked complete. migrations/1788256455.sh:49 (

) prints a retry instruction when backup/elevation fails but returns success. Likewise, a verification failure restores the vulnerable backup and returns success. omarchy-migrate then creates the completion marker, so it never retries. Both paths must exit nonzero after any necessary restoration.

@Adolanium

Copy link
Copy Markdown
Contributor Author

I think this landed on the wrong PR. The migration, the PAM predicate, and the linked commit 8a13eac are from #9873 by @Wheel-Smith. This PR only touches omarchy-hook and omarchy-state.

The three points look worth raising there, so you may want to move the comment over to #9873.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants