From 8a13eac872988c722be4cb4765211593b61d6de9 Mon Sep 17 00:00:00 2001 From: rattatui <88578725+Wheel-Smith@users.noreply.github.com> Date: Wed, 2 Sep 2026 21:41:53 +0300 Subject: [PATCH] Defer to system-auth in the polkit stack written by fingerprint/FIDO2 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 --- bin/omarchy-setup-security-fido2 | 8 +-- bin/omarchy-setup-security-fingerprint | 8 +-- migrations/1788256455.sh | 52 +++++++++++++++++++ test/shell.d/security-polkit-faillock-test.sh | 32 ++++++++++++ 4 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 migrations/1788256455.sh create mode 100644 test/shell.d/security-polkit-faillock-test.sh diff --git a/bin/omarchy-setup-security-fido2 b/bin/omarchy-setup-security-fido2 index 85fe2039..75a87124 100755 --- a/bin/omarchy-setup-security-fido2 +++ b/bin/omarchy-setup-security-fido2 @@ -31,11 +31,11 @@ setup_pam_config() { echo "Creating polkit configuration with FIDO2 authentication..." sudo tee /etc/pam.d/polkit-1 >/dev/null <<'EOF' auth sufficient pam_u2f.so cue authfile=/etc/fido2/fido2 -auth required pam_unix.so +auth include system-auth -account required pam_unix.so -password required pam_unix.so -session required pam_unix.so +account include system-auth +password include system-auth +session include system-auth EOF fi } diff --git a/bin/omarchy-setup-security-fingerprint b/bin/omarchy-setup-security-fingerprint index 383aa376..fd84d2db 100755 --- a/bin/omarchy-setup-security-fingerprint +++ b/bin/omarchy-setup-security-fingerprint @@ -47,11 +47,11 @@ setup_pam_config() { sudo tee /etc/pam.d/polkit-1 >/dev/null </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 + + echo "Rewriting $polkit to defer to system-auth (restores pam_faillock lockout)..." + + # Keep the configured hardware-auth auth lines verbatim (the clamshell gate and + # the pam_fprintd / pam_u2f 'sufficient' lines); only the bare pam_unix stack is + # replaced with the system-auth includes the vendor file and the sudo stack use. + hw_auth=$(grep -E '^auth' "$polkit" | grep -vE 'pam_unix\.so') + + rebuilt=$( + [[ -n $hw_auth ]] && printf '%s\n' "$hw_auth" + printf 'auth include system-auth\n' + printf 'account include system-auth\n' + printf 'password include system-auth\n' + printf 'session include system-auth\n' + ) + + backup="$polkit.omarchy-bak.$(date +%s)" + if sudo cp -a "$polkit" "$backup"; then + printf '%s\n' "$rebuilt" | sudo tee "$polkit" >/dev/null + + if grep -qE '^auth[[:space:]]+include[[:space:]]+system-auth' "$polkit"; then + echo "Restored polkit brute-force protection. Previous file saved at $backup." + 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 diff --git a/test/shell.d/security-polkit-faillock-test.sh b/test/shell.d/security-polkit-faillock-test.sh new file mode 100644 index 00000000..74582457 --- /dev/null +++ b/test/shell.d/security-polkit-faillock-test.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -euo pipefail + +source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh" + +# The fingerprint and FIDO2 setup commands each create /etc/pam.d/polkit-1 from +# scratch when the file does not already exist -- which is the normal case on +# Arch, where the polkit package ships its PAM stack in /usr/lib/pam.d/polkit-1 +# and /etc/pam.d/polkit-1 is absent. A hand-rolled stack that lists pam_unix +# directly instead of `include system-auth` silently drops pam_faillock, so +# polkit prompts would have no brute-force lockout and their failures would not +# count toward the shared tally. Assert the created stack defers to system-auth. + +for setup in omarchy-setup-security-fingerprint omarchy-setup-security-fido2; do + script="$ROOT/bin/$setup" + + # Pull the here-doc body the setup writes to /etc/pam.d/polkit-1. + body=$(sed -n "/tee \/etc\/pam.d\/polkit-1/,/^EOF\$/p" "$script") + + [[ -n $body ]] || fail "$setup writes a polkit-1 stack" + + for phase in auth account password session; do + grep -qE "^${phase}[[:space:]]+include[[:space:]]+system-auth" <<<"$body" || + fail "$setup polkit-1 $phase defers to system-auth (keeps faillock)" "$body" + done + + ! grep -qE "^(account|password|session)[[:space:]]+required[[:space:]]+pam_unix" <<<"$body" || + fail "$setup polkit-1 does not hand-roll a bare pam_unix stack" "$body" + + pass "$setup creates a polkit-1 stack that includes system-auth" +done