Open-source project
pallotron/yubiswitch avatar
pallotron/yubiswitch

yubiswitch and the YubiKey that kept typing into your Vim session

OSX status bar application to enable/disable Yubikey Nano

928 stars73 forksObjective-CNOASSERTION

At a glance

What is it?
yubiswitch is a macOS status bar application that enables and disables a YubiKey Nano or Neo through a global hot key, backed by a privileged helper daemon that takes exclusive control of the USB HID interface. It suits people who keep the key plugged in but do not want accidental one time passwords leaking into whatever window has focus.
Who is it for?
Adopt yubiswitch if you use a YubiKey Nano or Neo on macOS, keep it inserted, and want a hot key to stop the key from emitting one time passwords into whatever window you are typing in. Skip it if you need key switching for other hardware tokens, or if your organisation does not permit a signed helper with root privileges on the machine, since the exclusive grab of the USB HID interface requires it.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 35 days ago.
What is it written in?
Mainly Objective-C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The accidental OTP problem this app exists to solve

A YubiKey Nano has a gold contact on its edge. Touch it and the key types a one time password into whatever has focus, exactly as if a person had entered it on a keyboard. The security model depends on the user pressing the key deliberately, which works well until the key sits in a pocket or a hand while you are working.

The project documentation tells the story with a specific incident: a laptop carried to a meeting room, held in one hand with a finger on the gold stripe, sent random OTP passwords into a Vim session and into a chat window that was open with the author's wife. The key was working as designed. The problem was the scope of what typed into the keyboard means when the device is an HID keyboard.

yubiswitch is the answer to that specific problem. It is an OSX status bar application to enable and disable a YubiKey Nano or Neo from Yubico, and the switch is driven by a global keyboard hot key that you configure yourself. Nothing about the key changes. The app simply decides whether the device is allowed to talk to the system.

The audience is narrow and well defined: Mac users who carry a YubiKey daily, leave it plugged in, and want the keyboard's focus to be theirs alone.

Why a root helper daemon is required to switch the key

The architecture is the interesting part, and the documentation is candid about it. This application needs to run with escalated privileges in order to exclusively grab the USB HID interface that drives the NANO and NEO-n Yubikey.

Running the whole application as root would be unpleasant, so the design splits it. A helper daemon installs with root privileges and holds the logic to grab the USB HID interface. The main application talks to that daemon over XPC. When you start YubiSwitch for the first time it asks for your user's password, and the README explains that this is expected, since it is the helper being installed.

The consequence for you is that this is privileged software on your desktop. The helper is doing something that normally requires root: taking exclusive ownership of a USB HID device so that no other process, including the OS keyboard stack, competes for it. That exclusivity is what makes the on and off switch reliable rather than best effort.

The trade-off is inherent. If you want a keyboard-class device to be silenced on demand, you need control of the device class, and on macOS that means a privileged agent.

Installing the DMG and granting macOS privacy permissions

The download is a DMG from the GitHub release page, and there is no package manager route or build-from-source instruction in the documentation. You install the application bundle and move it where you want it.

On macOS Catalina (10.15) or later, the app needs Accessibility and Input Monitoring permissions, and the documentation is explicit about where to grant them. Open System Preferences, go to Security & Privacy, then Privacy. Under Accessibility, click the lock to make changes and use the plus button to add `/Applications/yubiswitch.app/`, and repeat the same under Input Monitoring.

Both permissions are needed because the app registers a global hot key, and macOS treats global keyboard hooks as an accessibility level privilege.

The README also warns about a signature detail: Yubiswitch is signed and notarised by the Supratude Limited developer account, so if you see that name in the macOS security prompt, this is expected rather than a sign of tampering.

AppleScript KeyOn and KeyOff for shell integration

The application supports two basic AppleScript commands, KeyOn and KeyOff, which makes it usable from a shell script or from another automation rather than only by clicking the menu bar icon.

bash
$ osascript -e 'tell application "yubiswitch" to KeyOn'
bash
$ osascript -e 'tell application "yubiswitch" to KeyOff'

The two commands are the useful part of this for anyone scripting a workstation: a login item can turn the key off, a script can switch it on only while a particular tool is in use, and a test can assert the state. The scripting definition is a file in the repository root called YubiSwitch.sdef, which is how the app declares the commands to the system.

There is a related macOS integration worth noting as well. If you use the YubiKey as part of multi-factor authentication for Mac, the documentation suggests making sure the option "Enable yubikey when system locks/sleeps" is enabled, so the key returns to a usable state after the machine suspends.

Finding the Product ID and Vendor ID before the key is recognised

If the app does not react to your key, the documented advice is to confirm the Product ID and Vendor ID. Three routes are documented.

The graphical route uses the System Information app, opened with `CMD + Space` and typed as `System Information`. In the left sidebar you click on USB and find your OTP/FIDO/CCID entry.

The terminal route uses ioreg.

bash
$ ioreg -p IOUSB -l -w 0 -x | grep -i Yubikey -A10 | grep 'idProduct\|idVendor'
          "idProduct" = 0x116
          "idVendor" = 0x1050

The README notes that the `-x` for ioreg is important, because it is what makes the idProduct field display in hexadecimal.

A third route exists for people who prefer lsusb style output, using Homebrew.

bash
$ brew update && brew tap jlhonora/lsusb && brew install lsusb

$ lsusb | grep -i Yubikey
Bus 020 Device 022: ID 1050:0116 1050 Yubikey NEO OTP+U2F+CCID

The example output is worth reading carefully, because it exposes the default behaviour that trips people up. The vendor ID is 1050, which is Yubico, and the product ID identifies the specific model.

The Product ID field defaults to controlling every Yubico device

The first entry in the Known Issues section is a security-relevant default that deserves more attention than its position in the list suggests. By default the app controls any Yubico device, regardless of its Product ID. To restrict control to specific models, you leave the `Product ID` field in Preferences blank, and to narrow it you enter a comma-separated list of hex Product IDs, for example `0x0010,0x0407`, so that only those are controlled.

The wording is easy to read backwards, so restate it plainly. Blank means every Yubico device is under the app's control. A populated list restricts it. If you work in an environment where a second person's key might be plugged into your machine, the default is broader than you may want.

Other known issues in the same list are more mundane. The app only works with recent versions of OSX because it relies on the Notification Centre, so 10.8.x and above are needed. If the Product ID and Vendor ID are correct and the app still is not working, the documented path is to follow the uninstall instructions and update to the latest release. There is also a specific bug in the preference named `Switch off Yubikey after __ seconds`, where the float value causes trouble for the `Automatically switch off Yubikey` option and converting the value to an int fixes it.

Locking the screen when the key is pulled, and the release packaging

If you want yubiswitch to lock the computer when you unplug the key, the documentation points at the screensaver security settings, and the matching feature appears in the completed items of the project plan as lock computer when yubikey is removed.

The plan also records other features that are already in place, and they tell you what the app can be expected to do. The hot key is configurable through a configuration window, done via ShortcutRecorder, and it is no longer static at cmd-Y. Preferences changes are broadcast with NSNotificationCenter between the AppDelegate and the YubiKey class. There is a "Start at login" feature. Support for more Yubikeys on multiple USB slots is present, along with better handling of plug and unplug events.

ShortcutRecorder is also a hard dependency rather than an optional one: it implements the global hot key and the shortcut recording in the preference window, and it is vendored in the repository as a git submodule in a ShortcutRecorder directory.

Distribution is a manual process that has not been automated. You sign all applications and frameworks and the dmg file itself, using the bash script `createdmg.sh`, and you sign the app with an official Mac developer profile. A release means tagging the repository with `git tag -a -m 'comment that describe the changes' v0.2`, archiving the build from Xcode, running `cd dmg/ && bash createdmg.sh <PATH TO APP>`, and attaching the resulting file at `/tmp/yubiswitch_$VERSION.dmg` to the release on the GitHub page.

Editorial conclusion

Adopt yubiswitch if you use a YubiKey Nano or Neo on macOS, keep it inserted, and want a hot key to stop the key from emitting one time passwords into whatever window you are typing in. Skip it if you need key switching for other hardware tokens, or if your organisation does not permit a signed helper with root privileges on the machine, since the exclusive grab of the USB HID interface requires it. Before installing, note that the application is signed and notarised by the Supratude Limited developer account, so a Gatekeeper prompt naming that account is expected, and check the Product ID field in Preferences, which is blank by default and therefore controls any Yubico device attached to the machine.

Frequently asked questions

What does yubiswitch do on macOS?

It is a status bar application that enables and disables a YubiKey Nano or Neo with a configurable global hot key, so the key stops emitting one time passwords into whatever window currently has focus. The privileged helper daemon grabs the USB HID interface and the main app talks to it over XPC.

How do I control yubiswitch from the shell?

The app supports two AppleScript commands, KeyOn and KeyOff, invoked with osascript. For example: osascript -e 'tell application "yubiswitch" to KeyOff'.

Why does yubiswitch need Accessibility and Input Monitoring permissions?

It registers a global keyboard hot key, and macOS treats global keyboard hooks as an accessibility level privilege. On Catalina 10.15 or later you add /Applications/yubiswitch.app/ under both Accessibility and Input Monitoring in Security & Privacy.

Which YubiKey models does yubiswitch control by default?

By default it controls any Yubico device regardless of its Product ID. To restrict that, enter a comma-separated list of hex Product IDs such as 0x0010,0x0407 in the Preferences, leaving the field blank keeps the broad behaviour. Finding the IDs is done through System Information or the ioreg command shown in the documentation.

Official sources

  1. Issues
  2. pallotron/yubiswitch on GitHub
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pallotron-yubiswitch.svg)](https://hysenlabs.com/projects/pallotron-yubiswitch)

Was this useful?