rentzsch.com: tales from the red shed

Terminal.app's "Secure Keyboard Entry"

Mac OS X
There was a new command added to 10.3's version of Terminal.app: File -> "Secure Keyboard Entry".

So, what does this command do? Why should I enable it? Don't I want my keyboard entry to be secure all the time?

The only documentation I can find comes from Terminal.app's own Help entry:

You can set up Terminal to allow secure keyboard entry. This prevents other applications on your computer or the network from detecting and recording what you type in Terminal. Before you turn this option on, make sure other applications on your own computer don't need this information.

The docs aren't clear on exactly how other applications on your computer can "detect and record what you type in Terminal". The answer is GetKeys().

GetKeys() returns a bitmap of the keyboard's current state. That is, whether each and every key is up or down. The call is handy if you're writing a game that lacks a traditional event loop or callback model, or if you just want to see if the command, shift, space and "4" keys are all down at once.

However you can browbeat GetKeys() into becoming a general system-wide keystroke logger. You just have to poll it somewhat often (100 times per seconds seems to do the job for me), look for changes in the keyboard's state and then reconstruct the virtual keycodes from the resulting bitmap. Well, the format of virtual key codes has never been documented, but you can reverse-engineer it from Apple sample code.

I whipped up a small proof-of-concept application that should display everything you type into any application: GetKeystrokes. Source included.

As expected, my little app goes deaf when you enable Terminal.app's "Secure Keyboard Entry", so you can enter those ssh passwords with confidence. Some notes:

  • Terminal.app has a bug. If you enable "Secure Keyboard Entry", quit Terminal.app and restart it, the menu item will still have the checkmark, as if the feature has been reenabled. But it lies! Deselecting the menu item and reselecting it does successfully reenable the feature, however. Radar 3815685.
  • Apps which examine GetKeys() to determine an event's modifier state will fail, system-wide, if "Secure Keyboard Entry" is enabled. This generally isn't a problem, since well-written applications examine the correctly-populated event record fields to determine modifiers, rather than calling GetKeys() directly. However, I know I've been in tight spots where an event record is nowhere to be found, and I've needed to identify the current modifiers by calling GetKeys(). So watch out for subtle application breakage if you leave this feature on for extended periods.
  • Yeah, I know my app doesn't capture the shift key, caps lock, delete, etc. Send me a patch that does (grin).
  • Applications that type for you, like PasswordWallet, will probably fail with Secure Keyboard Entry enabled. That's because they use CGPostKeyboardEvent(), which gets horribly confused if you call it and the user is still pressing any key on the keyboard. The standard work-around is to poll GetKeys(), waiting for the user to release all keys before calling the function. Obviously this work-around fails when GetKeys() is transmogrified into a no-op, and the keyboard always reads untouched.
  • NSSecureTextField isn't really secure, system-wide. This includes the screen saver password protection. Radar 3815219.
  • My application will pick up virtual key presses created with CGPostKeyboardEvent(), which I wasn't expecting at all. This means my app will capture PasswordWallet as it autotypes the password. Yikes!
  • System-wide hotkey event handlers installed via RegisterEventHotKey() also seem to go deaf when Secure Keyboard Entry is enabled. I suppose this is to stop a rogue app from registering a hotkey on every key on the keyboard...

Update: Password Wallet 3.0.6 now uses EnableSecureEventInput()/DisableSecureEventInput()/IsSecureEventInputEnabled() (from HIToolbox/CarbonEventsCore.h) to disable cross-application snooping while it's typing for you and when you're entering/editing passwords within the app.

Update: Security Update 2004-12-02 fixes the Terminal.app bug mentioned above. It's also the first time I've been given credit in a Security Update. Woohoo!

Friday, September 24, 2004
12:00 AM