Skip to content

Report Secure Keyboard Entry as itself, not as an Input Monitoring denial - #9

Merged
camwilso merged 2 commits into
mainfrom
fix/secure-input-attribution
Aug 14, 2026
Merged

Report Secure Keyboard Entry as itself, not as an Input Monitoring denial#9
camwilso merged 2 commits into
mainfrom
fix/secure-input-attribution

Conversation

@camwilso

Copy link
Copy Markdown
Owner

Fixes #2.

When another process holds Secure Keyboard Entry, the pad's key events stop arriving and the app blamed Input Monitoring — a permission that was in fact granted, sending the user to reset the wrong thing (issue #2's five-hour trail).

  • PermissionProbe.secureInput() reads IsSecureEventInputEnabled() plus the holder pid the window server records in the IORegistry, resolved to an app name (NSRunningApplication, with a ps fallback for CLI processes).
  • A holder pid that no longer maps to a live process is named as a stale claim, with the log-out remedy — the exact case that burned ebowman.
  • DeviceStatus gains a dedicated case so the popover and log say "Secure Keyboard Entry is on (held by )" instead of misreporting a granted permission as denied.
  • The two BoardController sites that previously mapped silent input to accessDenied now disambiguate first.

Hardware-validated on the pad: probe verified against a real Secure Input holder, paint round-trip confirmed while engaged. 470/470 tests after rebasing onto current main.

🤖 Generated with Claude Code

camwilso and others added 2 commits August 14, 2026 08:40
… the cause

Secure Keyboard Entry produces the same kIOReturnNotPermitted as a revoked
Input Monitoring grant, and both paths blamed Input Monitoring — sending
people to a settings pane where the switch was already on (issue #2).

- PermissionProbe.secureInput(): IsSecureEventInputEnabled plus the holder
  pid the window server records on IOConsoleUsers, resolved to an app name.
  A dead holder is named as a stale claim with the logout remedy.
- CodexError.accessDenied text is now neutral; attribution happens where
  the error surfaces, probe in hand.
- publishDeviceStatus: new secureInputBlocked device status on the open
  path, checked after the grant (the durable problem wins).
- The paint-failure log names Secure Input and its holder on the write
  path — the mid-session engage the periodic poll never covered.

Hardware-validated on a Codex Micro: paint succeeds normally, fails with
the neutral text while a scratch process holds Secure Input — open
succeeded, write refused, the exact uncovered path from the report.

Fixes #2

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h that is not there

hookCommandPath appended Contents/MacOS to bundleURL, which is the .app for
an installed copy but the enclosing folder for a bare swift-build executable
— so a debug build's Repair wired every session to a path that does not
exist, silently, since the helper exits 0 by design. Now the path derives
from executableURL's parent (correct in both layouts), audit checks
existence before path equality (stalePath could never fire for our own
path), and install refuses a command that is not an executable file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@camwilso
camwilso merged commit 610d205 into main Aug 14, 2026
1 check passed
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.

"Input Monitoring" denial is misreported when the real cause is Secure Keyboard Entry

1 participant