Skip to content

Gate sudo fingerprint behind lid state (clamshell)#6003

Open
ocewers wants to merge 2 commits into
basecamp:devfrom
ocewers:fingerprint-lid-aware
Open

Gate sudo fingerprint behind lid state (clamshell)#6003
ocewers wants to merge 2 commits into
basecamp:devfrom
ocewers:fingerprint-lid-aware

Conversation

@ocewers
Copy link
Copy Markdown

@ocewers ocewers commented May 30, 2026

Problem

When fingerprint auth is set up, omarchy-setup-security-fingerprint inserts auth sufficient pam_fprintd.so at the top of /etc/pam.d/sudo. Because it is first and sufficient, pam_fprintd grabs stdin with "Place your finger…" and blocks the password prompt until it times out.

In clamshell mode (laptop lid closed, docked to an external display) the reader is physically unreachable, so every sudo forces an awkward wait before you can type your password.

Fix (sudo only)

Run pam_fprintd only when the lid is open. PAM can't read lid state, so a tiny pam_exec helper (/usr/local/bin/omarchy-lid-open) gates it:

auth    [success=ignore default=1] pam_exec.so quiet /usr/local/bin/omarchy-lid-open
auth    sufficient                 pam_fprintd.so
auth    include                    system-auth        # (unchanged)
  • Lid open → helper exits 0 → success=ignore → falls through to pam_fprintd → fingerprint as before.
  • Lid closed → helper exits 1 → default=1 → jumps over the fprintd line → straight to the password stack.
  • Helper missing / errors / lid state unknown → non-success → default=1 → password. Fail-safe: never a lockout.

Scope & safety

  • sudo only. /etc/pam.d/polkit-1 is intentionally left as-is — the polkit agent shows a password field in parallel with fingerprint, so it never blocks the way terminal sudo does.
  • Desktops / non-laptops untouched. has_lid() is false when there is no /proc/acpi/button/lid/*/state, so setup inserts only the plain pam_fprintd line (today's behavior), no helper is installed, and the migration no-ops. A laptop with no ACPI lid button is treated like a desktop (fix simply doesn't engage).
  • pam_exec ships with the base pam package — no new dependency.
  • The helper lives in /usr/local/bin (not repo bin/, which is only on the user's $PATH) so PAM as root has a stable absolute path. Installed via sudo tee, mirroring the existing polkit-1 heredoc.

Changes

  • bin/omarchy-setup-security-fingerprint: has_lid(), install_lid_helper(); on laptops insert the lid guard above the sudo pam_fprintd line. polkit untouched.
  • bin/omarchy-remove-security-fingerprint: strip the guard from sudo and remove the helper.
  • migrations/1780152390.sh: upgrade existing laptop installs idempotently; no-op on desktops.

Testing

Verified locally on a ThinkPad X1 Carbon gen 14 (Omarchy 3.8.2):

  • bash -n clean on all three scripts.
  • Helper tested against real /proc (lid open → exit 0), simulated closed lid (exit 1), and no-lid/desktop (exit 0).
  • Applied the migration on a live /etc/pam.d/sudo (with backup) and exercised sudo -k; sudo true in both lid states: lid open prompts for fingerprint as before; lid closed (clamshell on external monitor) goes straight to the password prompt with no fingerprint wait. Toggled back and forth repeatedly with consistent results.

🤖 Generated with Claude Code

When fingerprint auth is set up, pam_fprintd is inserted first and
`sufficient` in /etc/pam.d/sudo, so it blocks the password prompt with
"Place your finger…". In clamshell mode (lid closed, docked to an external
monitor) the reader is unreachable, forcing an awkward wait before every sudo.

Gate pam_fprintd behind a small pam_exec helper that checks the laptop lid
state, so fingerprint is only attempted when the lid is open and sudo falls
straight through to the password stack when the lid is closed.

- sudo only; polkit is left as-is (its GUI dialog shows a password field in
  parallel and never blocks the way terminal sudo does)
- desktops / machines without an ACPI lid button are untouched
- fail-safe: helper missing / errors / unknown lid state -> password, never lockout

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 30, 2026 14:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a lid-state guard so that sudo fingerprint authentication is skipped when a laptop lid is closed (e.g., clamshell mode), preventing sudo from hanging on an unreachable reader. A small helper script (omarchy-lid-open) is installed and invoked via pam_exec before pam_fprintd. A migration applies the same guard to existing installs, and the remove script cleans it up.

Changes:

  • New migration script that installs the lid helper and inserts a pam_exec guard above pam_fprintd.so in /etc/pam.d/sudo on laptops.
  • omarchy-setup-security-fingerprint now detects an ACPI lid, installs the helper, and inserts the PAM guard during fresh setup.
  • omarchy-remove-security-fingerprint strips the PAM guard line from /etc/pam.d/sudo and removes the helper binary.

Reviewed changes

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

File Description
migrations/1780152390.sh Backfills lid-guard helper and PAM rule on existing systems with fingerprint sudo
bin/omarchy-setup-security-fingerprint Adds has_lid/install_lid_helper and inserts the lid guard during setup
bin/omarchy-remove-security-fingerprint Removes the lid guard PAM line and deletes the helper binary

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread migrations/1780152390.sh
Comment on lines +13 to +21
sudo tee /usr/local/bin/omarchy-lid-open >/dev/null <<'EOF'
#!/bin/bash
# omarchy:summary=Exit 0 if the laptop lid is open (used by PAM to gate fingerprint auth)
for f in /proc/acpi/button/lid/*/state; do
[[ -r "$f" ]] || continue
grep -q open "$f" && exit 0 || exit 1
done
exit 0
EOF
Copy link
Copy Markdown
Author

@ocewers ocewers May 30, 2026

Choose a reason for hiding this comment

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

Thanks for the catch. I went back and forth on this one.

These migrations are run-once, self-contained snapshots: omarchy-migrate executes each file with bash $file, records it in the state dir, and never touches it again. Keeping the helper body inline here is deliberate so the migration reproduces exactly what shipped at this point in time, independent of any later change to install_lid_helper. The single ongoing source of truth is install_lid_helper in omarchy-setup-security-fingerprint; the migration's copy is frozen at merge and won't need to be kept in sync.

I considered extracting the helper into a shared shipped file that both consumers install, but the natural home (bin/omarchy-lid-open) would surface it as an omarchy-lid-open entry in omarchy commands (it carries an # omarchy:summary= header) for what is really an internal PAM helper. Happy to go that route and drop the summary header if you'd prefer a single physical copy — let me know.

Comment thread migrations/1780152390.sh
Comment on lines +16 to +19
for f in /proc/acpi/button/lid/*/state; do
[[ -r "$f" ]] || continue
grep -q open "$f" && exit 0 || exit 1
done
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This (the && exit 0 || exit 1 idiom) is now fixed in both places.

Address review feedback: the `cmd && exit 0 || exit 1` idiom is a known
footgun and obscures intent. Spell it out as an if/else in both the setup
helper and the migration's copy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

2 participants