macOS has no single API you can plug a fingerprint into. immurok meets each authentication surface with the right mechanism — PAM, credential injection, or a GUI bridge — and keeps a hard security boundary around each. Here's the map, and an honest risk analysis.
There is no one place in macOS where you can say “a fingerprint touch counts as the password.”
sudo goes through PAM. The App Store shows its own sheet. Screen unlock is a special world the system guards tightly. “Sign in with Apple” is rendered by a separate helper process. Each surface expects a different kind of proof.
So immurok doesn’t have one trick — it has three, and it picks the right one per surface. The unifying principle underneath is simple: the device only ever proves that a real, authenticated touch happened; the host decides what that touch is allowed to unlock. (How the device proves it — ECDH pairing, HMAC-signed events, biometrics that never leave the sensor — is the subject of the immurok security model. This post is about the host side.)
Path 1 — PAM + BLE: the device proves it
sudo, SSH key signing, and the system’s GUI authorization prompts all run a PAM stack. immurok ships a tiny module, pam_immurok.so, that sits at the front of the relevant /etc/pam.d services. When one of them authenticates, the module opens a Unix socket to the companion app, which asks your paired device for a challenge-response over BLE. Touch the sensor, the device returns a signed OK, PAM succeeds.
The important part: no password is involved anywhere. The credential is the cryptographically signed touch. There is nothing to store and nothing to type.
Path 2 — Credential injection: the host fills the field
The App Store, the Passwords app, and Safari’s “Sign in with Apple” sheet don’t go through PAM. They put a real secure text field on screen and wait for you to type. immurok watches the system’s focused accessibility element; when a whitelisted app focuses an AXSecureTextField, immurok writes the stored secret straight into it through the accessibility API and presses the sheet’s confirm button.
Two subtleties make this safe and possible:
- It writes the value (
kAXValue), it doesn’t synthesize keystrokes — so macOS’s Secure Event Input, which blocks fake typing into password fields, doesn’t apply. - The secret it writes lives in the Keychain (your login password, or your Apple ID password), never on the device and never over BLE.
Path 3 — The GUI bridge: host submits, PAM proves
Some GUI dialogs (the standalone SecurityAgent window) do run PAM, but only after a human clicks a button. immurok bridges the gap: on a touch it arms a short pre-authorization window scoped to the authorization service, then submits the field so the PAM chain runs and the pre-auth answers it. Screen unlock is the extreme case — PAM can’t dismiss a locked screen at all — so there the device simply types your password over its BLE HID keyboard.
Where the credential lives
The three paths differ most in one thing that matters for security: whether a real secret sits on your Mac at all.
The PAM path stores nothing — that’s its great property. The injection path buys convenience on surfaces PAM can’t reach, at the cost of keeping an actual password on the machine. immurok narrows that cost deliberately: secrets go in the Keychain, are captured only when you enable the feature, and are wiped the moment you turn it off.
Honest risk analysis
- Injection leans on an OS behavior Apple could restrict. Writing a value into a secure field via accessibility is allowed today; a future macOS could lock it down. That’s why the device keeps a keyboard: HID typing is the fallback, and the pure-PAM paths don’t depend on it at all.
- The code-signature check is the anti-spoofing anchor. Matching bundle id alone would be forgeable; requiring
anchor appleon the target’s running process is what stops a malicious app from posing as a trusted one to harvest an injected secret. - A stored secret is a new local attack surface. The injection paths trade the PAM path’s “nothing on disk” property for reach. Keychain storage, on-demand capture, and clear-on-disable shrink the window, but a compromised host with the feature on can recover those secrets — a pure-PAM setup can’t.
- The pre-auth window is a small race surface. Scoping it to one service, making it single-use, timing it out in seconds, and requiring a focused password field keep it tight, but it is the one moment where a same-UID process could try to slip in. We keep it as narrow as the UX allows.
The takeaway is the same principle we started with, now with teeth: prove where macOS lets us, fill where it doesn’t, and never hand out authority without explicit, scoped, signed intent.
superdog
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.