Hello,
We have a service (daemon) that requires keystroke monitoring and runs under the new "Input Monitoring" policy ( starting from Catalina) .
The problem is when I run the daemon from Xcode I do receive the standard "keystroke receiving" prompt.
When the service runs as a daemon or as a console application there is no "keystroke receiving" prompt at all.
Also, when there are no apps added in the "Input monitoring" list, the button add ("+") is not even shown.
Thus, it's even impossible to add manually our service (daemon) to that policy.
As the result, the service is not functioning at all with the "TCC deny IOHIDDeviceOpen" error.
But I never got any prompts neither for a console app nor for a daemon.
The question is how we must ship the service (daemon) the get the proper "keystroke receiving" prompt?
Our service ships without a bundle, just as a console application with a daemon plist.
As for a test, I tried to create an application bundle doing some IOHIDDeviceOpen requests, and I got the "keystroke receiving" prompt.
But I don't think it will be good to ship the daemon within an application bundle.
Any ideas how get the prompt for a daemon case?
Thanks in advance!
Ah, that’s interesting. In general, daemons should not be doing anything with input events because such events are the preserve of the window server (for more background on this, see Technote 2083 Daemons and Agents). However, you’re doing this using
IOHIDDevice
, which is part of I/O Kit, and thus daemon safe.
When the service runs as a daemon or as a console application there is no "keystroke receiving" prompt at all.
Given that you’re running outside of the user context, you’re never going to get a TCC prompt. This was a deliberate design decision. We only issue TCC problems for things that we can specifically relate to the GUI login session.
Also, when there are no apps added in the "Input monitoring" list, the button add ("+") is not even shown.
Right. This is a known bug (r. 55284204).
You should be able to make this work by:
Placing your daemon code inside an app.
Having it launchable as an app from the GUI.
At this point it can trigger the Input Monitoring TCC request. If the user OKs that, it’ll apply to all further instances of that code running.
Having your daemon launch the app with an argument that causes it to enter daemon mode.
I’ve played around with this a lot in similar contexts and it has worked well for me. I have not, however, tested your specific case, that is, a daemon using
IOHIDDevice
. You should give a whirl and see how you get along.
Finally, a word of caution about daemon placement. A daemon runs as root, and thus it’s not safe to locate the daemon within
/Applications
, either directly or within another app. Doing so will create an unchecked admin-to-root privilege escalation security vulnerability (because
/Applications
is writeable by all admin users, so an admin user can move your daemon out of the way and replace it with their own code without any authentication).
As to where you /should/ place your daemon, that kinda depends on the nature of your product as a whole. My general recommendation is
/Library/Application Support/***/MyDaemon.app
, where
***
contains either your company or product name. This recommendation is based on a number of criteria:
The
directory is only writeable by root./Library/Application Support
The
ensures that you don’t collide with other products.***
The daemon is visible in the Finder, so the user can launch it in order to trigger a TCC prompt, as I discussed above.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"