kCGSSessionSecureInputPID wrong when secure event input enabled from background app

Number:rdar://48953777 Date Originated:2019-03-16
Status:Open Resolved:
Product:macOS / Core Graphics Product Version:10.14.3 (18D109)
Classification:Severe Reproducible:Always
The ioreg key IOConsoleUsers / kCGSSessionSecureInputPID should hold the process ID of the process which called EnableSecureEventInput(). If an application calls EnableSecureEventInput() while inactive (i.e. in the background), kCGSSessionSecureInputPID will report the PID of the application which is active at the time the inactive application calls EnableSecureEventInput().

Steps to Reproduce:
1. Download the attached DelayedSecureInput.zip file
2. Unzip the file and note the location of the resulting DelayedSecureInput folder
3. Launch the DelayedSecureInput application
4. Within 5 seconds of #3, click on another app (such as Finder or Xcode)
*. DelayedSecureInput should show "Secure input is enabled" before you proceed
5. Launch the "Secure Input Detective" script application

Expected Results:
Secure input has been enabled by the application "DelayedSecureInput."

Actual Results:
Secure input has been enabled by the application "<active app from step #4>."

macOS 10.14.3 (18D109)

MacBook Pro (15-inch, Late 2016)
2.9 GHz Intel Core i7
Radeon Pro 460 4GB

Alternative Repro Step:
I included the Secure Input Detective script application and its source for convenience.

If you'd prefer to use Terminal to see the value of kCGSSessionSecureInputPID, substitute this Terminal command for step #5:

ioreg -l -w 0 | grep kCGSSessionSecureInputPID

Note that the process ID shown will not match the process ID of the DelayedSecureInput application.

Why does this matter? We make TextExpander, which uses a CGEventTap to filter keystrokes. Frequently, TextExpander fails to receive events because another application has called EnableSecureEventInput() and failed to call DisableSecureEventInput(). TextExpander has a timer-based method to check IsSecureEventInputEnabled(), and when true uses kCGSSessionSecureInputPID to determine the name of the process holding us hostage and report that to the user, as the user is the only one who can resolve that situation.

I ran into this bug because if Chrome is in the background and a service times out and asks for your password (think: online banking / accounting software / etc.), Chrome calls EnableSecureEventInput() while inactive. TextExpander winds up reporting to the user that whatever application was active at the time this occurred is holding secure event input. The user quits that application, but it doesn't resolve the problem. The user gets angry, and rightly so. Unfortunately, they get angry at TextExpander, when it's not really our fault.

One can certainly argue that an application should not call EnableSecureEventInput() when inactive, and I'll report that as a Chrome bug. However, given that it is _possible_, even easy to do this, I think it's important that kCGSSessionSecureInputPID accurately reflect the process ID of the application which called EnableSecureEventInput() even if it's inactive at the time of the call.



Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!