Defer to system-auth in the polkit stack written by fingerprint/FIDO2 setup - #9873
Defer to system-auth in the polkit stack written by fingerprint/FIDO2 setup#9873Wheel-Smith wants to merge 2 commits into
Conversation
… setup The fingerprint and FIDO2 setup commands create /etc/pam.d/polkit-1 from scratch on Arch, where the polkit package ships its stack in /usr/lib/pam.d/polkit-1 and /etc/pam.d/polkit-1 does not exist. The hand-rolled stack listed pam_unix directly instead of including system-auth, which dropped pam_faillock from the polkit path: polkit prompts had no brute-force lockout, their failures were not recorded, and they did not count toward the lockout protecting login and sudo. Defer to system-auth, matching the vendor file and the sudo stack, keeping the clamshell gate and the pam_fprintd / pam_u2f sufficient lines in front. Add a migration to repair installs the old setup already configured, since the forward fix does not rewrite an existing polkit-1. It acts only on an Omarchy-created polkit-1 that lacks the system-auth include and carries a hardware-auth marker, preserves the configured auth lines, backs up the original, and is idempotent. Add a test asserting the stack each setup creates defers to system-auth; the created polkit content was previously untested. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
The migration can permanently skip failed repairs and leaves markerless legacy configurations vulnerable.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Restores pam_faillock protection for polkit authentication configured with fingerprint or FIDO2.
Changes:
- Delegates generated polkit PAM stacks to
system-auth. - Adds migration logic for existing installations.
- Adds regression tests for generated configurations.
File summaries
| File | Description |
|---|---|
test/shell.d/security-polkit-faillock-test.sh |
Verifies generated stacks include system-auth, but lacks migration coverage. |
migrations/1788256455.sh |
Repairs legacy overrides, but misses markerless configurations and incorrectly succeeds on failures. |
bin/omarchy-setup-security-fingerprint |
Uses system-auth in generated polkit configuration. |
bin/omarchy-setup-security-fido2 |
Uses system-auth in generated polkit configuration. |
Review details
Suppressed comments (1)
migrations/1788256455.sh:22
- This predicate does not prove that Omarchy created the file: administrator-authored files under
/etc/pam.dare normally package-unowned, and any custom stack containingpam_fprintdor this FIDO2 authfile matches. The rebuild then discards all non-authcustom directives and comments. Restrict the migration to exact known Omarchy layouts, or patch only the known barepam_unixentries while preserving unrelated content.
grep -qE 'omarchy-hw-laptop-closed|pam_fprintd\.so|authfile=/etc/fido2/fido2' "$polkit"; then
- Files reviewed: 2/4 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| else | ||
| echo "polkit repair could not be verified; restoring the original file." >&2 | ||
| sudo cp -a "$backup" "$polkit" | ||
| fi | ||
| else | ||
| echo "Administrator privileges are required to repair $polkit. Run omarchy-migrate again from a terminal." >&2 | ||
| fi | ||
| fi |
| if [[ -f $polkit ]] && | ||
| ! pacman -Qo "$polkit" &>/dev/null && | ||
| ! grep -qE '^auth[[:space:]]+include[[:space:]]+system-auth' "$polkit" && | ||
| grep -qE 'omarchy-hw-laptop-closed|pam_fprintd\.so|authfile=/etc/fido2/fido2' "$polkit"; then |
| if [[ -f $polkit ]] && | ||
| ! pacman -Qo "$polkit" &>/dev/null && | ||
| ! grep -qE '^auth[[:space:]]+include[[:space:]]+system-auth' "$polkit" && | ||
| grep -qE 'omarchy-hw-laptop-closed|pam_fprintd\.so|authfile=/etc/fido2/fido2' "$polkit"; then |
…d tests Address review feedback on the polkit faillock migration: - Match only the exact stack the setup commands wrote and replace just the bare pam_unix lines, preserving comments and the hardware-auth lines. An administrator-authored polkit-1 carrying any other directive is left untouched, rather than rebuilt from scratch. - Also repair the markerless post-removal layout: both remove commands strip their own marker lines but leave the bare pam_unix stack behind, so keying on a hardware-auth marker skipped those machines permanently. - Exit non-zero when the backup cannot be created or the rewrite cannot be verified (after restoring). omarchy-migrate runs under set -e and records a migration complete unconditionally after it returns, so a failed repair must fail loudly to be retried instead of silently marked done. - Add test/shell.d/security-polkit-migration-test.sh covering the fingerprint, FIDO2, combined, and markerless layouts, comment preservation, idempotence, an untouched administrator stack, and the refused-sudo and unverifiable-write failure paths. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks for the careful review, @ErikMelton (and @Adolanium for redirecting it here from #8170). All three points were fair; I've addressed them in the follow-up commit, which reworks the migration and adds a test for it. 1. Overwriting administrator-authored PAM policy. The marker-based predicate is gone. The migration now recognizes only the exact stack the setup commands wrote — every non-blank, non-comment line must be one of the known hardware-auth 2. Post-removal installations remaining vulnerable. Correct — both remove commands strip only their own marker lines and leave the bare four-line 3. Failed repairs marked complete. Both failure paths now I also added |
Summary
Reported privately to security@omarchy.org first, per
SECURITY.md; opening this PR at the maintainer's request.omarchy setup security fingerprintandomarchy setup security fido2create an/etc/pam.d/polkit-1that does not defer tosystem-auth, which dropspam_faillockfrom the polkit authentication stack. On an affected machine, polkit password prompts have no lockout after repeated failures, those failures are not recorded in the shared faillock tally, and they do not count toward the lockout that protectsloginandsudo.sudoandloginthemselves are unaffected.Root cause
setup_pam_configbranches on whether/etc/pam.d/polkit-1already exists:On a stock Arch system that test is effectively always false: since pam 1.5.3 the polkit package ships its stack as a vendor file at
/usr/lib/pam.d/polkit-1, and/etc/pam.d/polkit-1does not exist. So theelsebranch runs and writes a new/etc/pam.d/polkit-1. Perpam.d(5), a file in/etc/pam.doverrides the vendor file of the same name, so this hand-written stack replaces the distro one.The hand-written stack lists
pam_unixdirectly instead of includingsystem-auth, sopam_faillock(andpam_env,pam_time,pam_limits,pam_systemd_home) never load on the polkit path. The vendor file it shadows is four lines ofinclude system-auth, and thesudostack the same setup edits keeps itsinclude system-auth— so only polkit is affected.omarchy-setup-security-fido2contains the identical branch and defect.Impact
At any polkit "Authentication Required" prompt (GUI privilege escalation: package installs, system settings, mounting, etc.) on an affected machine, a local attacker — session access, or local code running as the user that can trigger a polkit-authenticated action — can guess the password with no lockout (the policy elsewhere is
deny=10), without leaving a faillock audit trail, and without consuming the shared lockout budget that would otherwise trip onlogin/sudoand alert the user.This is a weakening of a brute-force/lockout control rather than a direct compromise; it is local-only and affects only machines that enabled fingerprint or FIDO2 auth. It also persisted after
omarchy remove security fingerprint/fido2, because the created file was left in place; with this change, once the hardware-auth lines are removed the remaining stack is the vendor-equivalentinclude system-auth.Changes
bin/omarchy-setup-security-fingerprint,bin/omarchy-setup-security-fido2— the file-creation branch now defers tosystem-auth, mirroring the vendor file and thesudostack, sopam_faillockis restored. The clamshell gate and thepam_fprintd/pam_u2fsufficientlines are kept in front unchanged.migrations/1788256455.sh— repairs machines the old setup already configured, since the forward fix does not rewrite an existing/etc/pam.d/polkit-1. It only acts on an Omarchy-createdpolkit-1(unowned by any package) that lacksinclude system-authand carries an Omarchy hardware-auth marker (the clamshell gate,pam_fprintd, or the FIDO2 authfile); it preserves the configured hardware-auth lines, backs up the original, re-verifies, and is idempotent. Administrator-authored files are left untouched.test/shell.d/security-polkit-faillock-test.sh— asserts the stack each setup creates defers tosystem-auth. There was previously no test on the created polkit content (the FIDO2 test mocks that write to/dev/null), which is why this went unnoticed. The test fails on the pre-fix scripts and passes with this change.Validation
Applied on an affected machine and confirmed end-to-end:
polkit-1) and the stack locks out atdeny=10, matchingsudoandlogin; the fingerprint line and clamshell gate are preserved../test/allpasses (the only failures on my checkout are the pre-existing ones that require a siblingomarchy-pkgscheckout and root-owned bind mounts, unrelated to this change).