Skip to content

Security: HMAKT99/UnTouchID

Security

SECURITY.md

Security Policy

Reporting Vulnerabilities

If you discover a security vulnerability in TouchBridge, please report it responsibly:

  1. Do NOT open a public issue
  2. Email: security@touchbridge.dev (or open a private security advisory on GitHub)
  3. Include: description, reproduction steps, impact assessment
  4. We will acknowledge within 48 hours and provide a fix timeline

Threat Model

What TouchBridge protects against

  • Remote authentication attacks: Biometric confirmation happens on a physical device you hold
  • Replay attacks: 32-byte nonces with 10-second expiry and 60-second seen-nonces window
  • Man-in-the-middle: ECDH ephemeral session keys with AES-256-GCM encryption on BLE channel
  • Key theft: Private signing key lives inside Secure Enclave — never exported, never leaves the chip

What TouchBridge does NOT protect against

  • Physical access to unlocked companion device: If someone has your unlocked iPhone, they can approve auth requests
  • Keychain items with kSecAccessControlBiometryCurrentSet: Cryptographically impossible — hardware ACL wall
  • Sandboxed third-party apps calling LAContext: Blocked by SIP and sandbox
  • Compromised macOS kernel: If the kernel is compromised, no user-space security holds

Availability note: PAM fallback vs. a dangling module reference

TouchBridge installs pam_touchbridge.so as auth sufficient, so if the daemon is down or the phone is unreachable, PAM falls through to your password — you are never locked out by a failed authentication.

There is one exception, and it is an availability issue, not an authentication bypass: if the module file is deleted while a PAM config still references it, sudo cannot initialize PAM and refuses to run entirely. The sufficient flag only falls through when the module loads and returns failure — a missing module file is a hard failure.

To avoid this, on macOS Sonoma+ we install the hook into the unprotected /etc/pam.d/sudo_local (Apple's sanctioned include) rather than the SIP-protected /etc/pam.d/sudo, and our uninstaller always removes the hook before the module. If you ever hit sudo: unable to initialize PAM: No such file or directory, recover without needing sudo (GUI admin auth uses a different PAM stack):

# Sonoma+ (hook in sudo_local — just delete it):
osascript -e 'do shell script "rm -f /etc/pam.d/sudo_local" with administrator privileges'

If /etc/pam.d/sudo itself is protected on your system and the hook was written there by an older version, the most reliable fix is to restore the module so the reference resolves again — download the latest .pkg, then:

pkgutil --expand-full TouchBridge-*.pkg /tmp/tb-x
osascript -e 'do shell script "cp /tmp/tb-x/Payload/usr/local/lib/pam/pam_touchbridge.so /usr/local/lib/pam/" with administrator privileges'

Cryptographic properties

Property Implementation
Nonce 32 bytes from SecRandomCopyBytes
Nonce expiry 10 seconds (hard minimum)
Replay protection Seen-nonces ring buffer, 60-second TTL
Signing algorithm ECDSA P-256 (ecdsaSignatureMessageX962SHA256)
Key storage (iOS) Secure Enclave (kSecAttrTokenIDSecureEnclave)
Key storage (Mac) Keychain (kSecAttrAccessibleWhenUnlockedThisDeviceOnly)
Session encryption AES-256-GCM over ECDH-derived key (HKDF-SHA256)
Transport BLE GATT (encrypted) or local Wi-Fi (Bonjour)

Audit logging

Every authentication event is logged to ~/Library/Logs/TouchBridge/ as NDJSON:

  • Session ID, result, device, surface, RSSI, latency
  • Nonce values are NEVER logged

Supported versions

Version Supported
1.0.x Yes
0.1.x No — upgrade to 1.0

There aren't any published security advisories