Cursor leaks Secure Event Input — breaks all system-wide input taps until quit or screen lock

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Cursor calls EnableSecureEventInput and never balances it with
DisableSecureEventInput. Secure Event Input is a system-wide singleton on
macOS, so while it is held, every CGEventTap on the machine is disabled —
not just inside Cursor.
The result is that any third-party tool relying on input taps silently
stops working for as long as the Cursor process lives. In my case
Logitech Options+ mouse gestures die; by the same mechanism this will
affect Raycast hotkeys, text expanders and dictation tools.
I hit this roughly 7 times per working day. The only reliable recovery is
locking and unlocking the screen, which resets the session’s secure-input
state.

Steps to Reproduce

  1. Launch Cursor and work normally for a few minutes.
  2. Check who holds secure input:
    ioreg -l -d 1 -w 0 | grep -o ‘kCGSSessionSecureInputPID"=[0-9]*’
  3. Resolve the PID:
    ps -p -o comm=
    Actual result
    kCGSSessionSecureInputPID"=29082
    /Applications/Cursor.app/Contents/MacOS/Cursor
    Held continuously for 14+ minutes with no password field focused anywhere
    in the UI. It does not clear on window blur, on app deactivation, or when
    another app is brought to the front. It clears only on Cursor quit or on
    screen lock/unlock.

Expected Behavior

Secure Event Input is released as soon as the secret input field loses
focus, and is guaranteed released on window blur / app deactivation so a
leaked enable cannot outlive the field that requested it.

Operating System

MacOS

Version Information

3.14.27

Additional Information

this is almost certainly not Cursor-specific code but inherited Electron/Chromium password-field behaviour, so the fix likely belongs in how Cursor handles focus teardown around masked input fields.

Does this stop you from using Cursor

Sometimes - I can sometimes use Cursor

Pulling the holder PID from ioreg and pinning it on Cursor is exactly right and saved us the guesswork.

This isn’t intended behavior and it’s not anything in your setup. To clear it whenever it sticks: fully quit and relaunch Cursor (Cmd+Q, then reopen) - the process exiting always releases the hold.

To pin the trigger, two quick things:

  1. What did you type into a masked field right before it stuck (Git/proxy credential, SSH passphrase, API key, or agent secret)?
  2. Does it still happen on the current version (Help → About; latest is 3.15.x)?

If handy, this catches the exact moment it sticks - whatever you did in the seconds before Cursor shows as holder is the culprit:

while true; do p="$(ioreg -l -d 1 -w 0 | grep -o '"kCGSSessionSecureInputPID"=[0-9]*' | grep -o '[0-9]*')"; printf '%s holder=%s %s\n' "$(date +%H:%M:%S)" "${p:-none}" "$(ps -o comm= -p "$p" 2>/dev/null)"; sleep 1; done

Thanks, that confirms it’s not something on my end.

Still on the current version?

I’m on 3.14.27 (haven’t taken 3.15.x yet — happy to update and re-test if
that’s more useful, just say). It is still reproducing on 3.14.27.

I can give you exact frequency rather than a guess. Since lock/unlock is my
recovery, every occurrence leaves an instant lock→unlock pair (1–3s) in the
screen-lock log, which is trivially distinguishable from a real break:

Aug 4 — 6 occurrences
Aug 5 — 7
Aug 6 — 3
Aug 7 — 4   (10:22, 10:36, 13:50, 14:01)

So roughly 4–7 times per working day.

What was typed into a masked field beforehand?

<< FILL IN: Git/proxy credential, SSH passphrase, API key, agent secret,
sudo in the integrated terminal, or “nothing I can recall” >>

One data point that may argue against the masked-field theory: on the
instance I captured, the holding process had only been alive for about
9 minutes and had already been holding the lock for 14+ minutes
continuously. Its log showed nothing but normal startup keychain init
(SecKeychainAddCallback / “Enabling System Keychain Always due to
platform”) at launch. No password field was open in the UI at capture
time, and it did not release on window blur or app deactivation.

That makes me suspect either something during startup, or an extension /
MCP auth path, rather than an interactive credential prompt.

Monitoring

I’ve got your watcher running (modified to log only ownership transitions
plus the frontmost app at that moment, so the trigger context is captured).
I’ll post the transition log the next time it sticks.

Minor note on the check: when nobody holds it, the
kCGSSessionSecureInputPID key is absent from IOConsoleUsers entirely
rather than set to 0 — so an empty result means “clean”, not “command
failed”.