Security and Permissions
Why Accessibility is required, what the encrypted transport protects, the trust model, and how to lock things down.
The two permissions MacKeyHost needs
MacKeyHost asks for two macOS permissions, both standard for any app that bridges the network into local input:
| Permission | Why MacKeyHost needs it | What happens without it |
|---|---|---|
| Accessibility | Posting synthetic CGEvents requires Accessibility. This is the same gate Karabiner-Elements, Rectangle, BetterTouchTool, and every macOS automation tool lives behind. | Events arrive at MacKeyHost — the on-screen counter ticks — but CGEvent.post returns silently with no effect. No keystroke reaches any Mac app. |
| Local Network | MultipeerConnectivity uses multicast and direct socket traffic on the local link. Without this permission, advertising still starts, but nothing on the network can see the Mac. | Vision Pro never finds the Mac in its picker. |
Both are granted once and persist across app launches and Mac reboots. macOS occasionally invalidates Accessibility grants — most commonly after a major macOS upgrade or after a code-signing change to the app — and the warning panel reappears in MacKeyHost's window. Re-enable it from System Settings.
Why Accessibility is the right level of permission
There is no narrower macOS API for "post one keystroke." The trade-off Apple has chosen is that an app either has full Accessibility (can post any event, can read screen contents via accessibility tree) or it can post nothing. MacKeyHost only uses the post-event half of Accessibility — it never reads the accessibility tree, never inspects window contents, never enumerates running apps. But the permission grant itself does not distinguish.
If that bothers you, your options are:
- Quit MacKeyHost when not in use. With Accessibility granted but the app not running, no events can be posted.
- Revoke Accessibility between sessions. Toggle it off in System Settings → Privacy & Security → Accessibility. Every relaunch will require re-granting.
In practice, option 1 is what most users do. The app launches in under a second.
What the encrypted transport protects
Multipeer Connectivity sessions in MacKeyHost are configured with encryptionPreference: .required. That means:
- Confidentiality. All traffic between Vision Pro and Mac is end-to-end encrypted with keys derived during the MPC handshake. Another device on the same Wi-Fi network cannot read your keystrokes by sniffing packets.
- Integrity. Modifications in transit are detected and the session is dropped.
- Forward secrecy. Each session uses a fresh ephemeral key. Compromise of the next session does not retroactively decrypt past sessions.
This is the same encryption used by AirDrop and Continuity Camera. Apple's design assumption is that a passive eavesdropper on the local Wi-Fi cannot extract any plaintext from an MPC session.
What the encrypted transport does not protect
The encryption protects the channel, not the endpoints. Specifically:
- Pairing is not authenticated. MacKeyHost auto-accepts every invitation. If two Vision Pros are nearby and one isn't yours, whichever invites first wins. Once paired, the link is encrypted, but you've now paired to a stranger.
- The Mac trusts whatever the paired Vision Pro sends. There is no signing, no per-event approval, no rate-limited burst detection beyond the 100-event-per-second cap. An attacker who pairs successfully has effectively keyboard-and-mouse access to the Mac for the duration of the session.
The mitigation is physical and network proximity. To pair, an attacker must:
- Be on the same Wi-Fi network as the Mac (Wi-Fi/AWDL transport), or
- Be physically within Bluetooth Low Energy range — a few meters at most (BLE transport).
In a private home or apartment with no untrusted devices on Wi-Fi, this is a low-probability threat. In a coffee shop, conference, or shared office, it is plausible.
Threat model: who can do what
| Actor | Can do | Cannot do |
|---|---|---|
| Stranger on the public internet | nothing | reach MacKeyHost — MPC is local-link only |
| Stranger on your Wi-Fi network with no vmux app | sniff encrypted packets, learn that an MPC session exists, see no plaintext | inject keystrokes |
| Stranger on your Wi-Fi network with vmux on a Vision Pro | pair if no other Vision Pro is currently connected and MacKeyHost is running | pair while you're already connected (sessions are exclusive) |
| Someone who steals the unlocked Mac | use the Mac normally as themselves | exploit MacKeyHost — it adds nothing to local console attack surface |
| App on the Mac without Accessibility | n/a | post events even if MacKeyHost is running and connected |
The most realistic abuse is a co-tenant on the same Wi-Fi network deciding to play with your Mac while you're not paired. The countermeasures, in order of effort:
- Quit MacKeyHost when you're done. No advertiser, no pairing, no risk.
- Lock the Mac when you walk away. Pair-and-inject doesn't bypass the login window — synthetic events are dropped at the lock screen because macOS uses Secure Input there.
- Use a more isolated network. Guest network, mobile hotspot, or no Wi-Fi (BLE-only). Reduces the pool of devices that can even see the advertised service.
Denying input from untrusted peers
There is currently no in-app block list, no device-whitelist, and no manual confirmation before MacKeyHost accepts an invitation. The way to deny an unwanted peer today is:
- Quit MacKeyHost. The advertiser stops, no one can connect.
- Toggle Wi-Fi or Bluetooth off. The local-link transports go away.
- Watch the status badge. If the Mac shows Connected to someone you don't recognize, quit immediately.
Future versions are expected to add an explicit pairing prompt and a remembered trusted-devices list. Until then, if you're in a sensitive environment, treat MacKeyHost as a tool you launch when you want input and quit when you're done.
Lock screen behavior
Like all third-party event injectors on macOS, MacKeyHost cannot inject keystrokes at the login window or at the system password prompt. macOS engages Secure Input at those points, which routes keyboard events directly to the authenticator and discards synthetic events from any source other than a real hardware keyboard.
The same mechanism protects:
- The login window after fast user switching or sleep
- Touch ID confirmation dialogs (the actual biometric prompt; you can still see and dismiss the dialog with mouse)
- Some password manager autofill prompts (1Password, KeePassXC) when they have Secure Input enabled
- Web browser password fields when the page or browser has opted in
This is intentional and not a bug. Type the password on the Mac directly; everything else can come from the Vision Pro.
Quitting and uninstalling
To stop accepting input without uninstalling, quit MacKeyHost from the dock or Cmd+Q. The advertiser stops, the open session (if any) is torn down, and the Mac becomes invisible to vmux.
To uninstall, drag MacKeyHost from /Applications to the Trash. The only state it leaves on disk is the Accessibility entry — to remove that, open System Settings → Privacy & Security → Accessibility, select vmux Mac Keyboard, and click the minus button.
There is no daemon, no launchd plist, no kernel extension, and no privileged helper. MacKeyHost runs only as your user, only while the app is open, and only with the permissions you've explicitly granted.
Related
- Security overview — App Lock, Secure Enclave, encrypted backups across the whole vmux suite.
- Pairing with Vision Pro — the trust handshake and how pairing actually completes.
- Input injection — what events flow through the link once paired.
- Troubleshooting — symptoms when permissions are wrong.