We are looking for a solution (API, Frameworks) that would allow us to block any type of external device, including storage devices, HIDs, network adapters, and Bluetooth devices according with dynamic rules that comes from management server . This feature is important for endpoint security solutions vendors, and it can be implemented on other platforms and older versions of macOS using the IOKit framework and kexts. I have found one solution that can control the usage only of "storage" devices with the EndpointSecurity framework in conjunction with the DiskArbitration framework. This involves monitoring the MOUNT and OPEN events for /dev/disk files, checking for devices as they appear, and ejecting them if they need to be blocked.. Also, I have found the ES_EVENT_TYPE_AUTH_IOKIT_OPEN event in EndpointSecurity.framework, but it doesn't seem to be useful, at least not for my purposes, because ES doesn't provide AUTH events for some system daemons, such as configd (it only provides NOTIFY events). Furthermore, there are other ways to communicate with devices and their drivers apart from IOKit. DriverKit.framework does not provide the necessary functionality either, as it requires specific entitlements that are only available to certain vendors and devices. Therefore, it cannot be used to create universal drivers for all devices, which should be blocked. Any advice would be greatly appreciated!
I agree that it's not particularly useful. I'd strongly encourage you to file an enhancement request asking for ES_EVENT_TYPE_AUTH_IOKIT_OPEN to include the io_object_t that's being targeted. That would make it FAR more useful.
Responding to myself I'm happy to announce that macOS 26 has expanded ES_EVENT_TYPE_AUTH_IOKIT_OPEN to address this.
From the ESMessage.h header doc:
* @field parent_registry_id The IOKit registry ID of the parent of the user class. Conceptually this is what the user class is
* connecting to. It can be resolved to a an `io_service_t` with by calling `IORegistryEntryIDMatching` then
* `IOServiceGetMatchingService`
* @field parent_path The path in the IOKit device tree to the class being opened. It can be resolved to an `io_registry_entry_t`
* by calling `IORegistryEntryFromPath`
A few notes/comments on the different fields here:
-
How unique the service path is depends on the specifics of the hardware involved. The path is fixed at the time a service attaches to the registry for devices where hot plug is involved, it's possible that different device might have the same path depending on the exact family involved.
-
While parent_path is a string path and can theoretically be parsed and interpreted, I generally recommend treating it as an opaque value. If you want to navigate the registry structure, convert it to a service and walk the registry directly.
-
The value returned by parent_registry_id is unique to every IOService, so the same physical device which loads to the same path will have a different ID between hotplugs.
-
In practice, both of these field could largely replace the other. Similarly, there probably is a performance difference when converting either to an io_service_t, but I would not expect that difference be large or for either value to be "slow".
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware