
Trust No One: Automating macOS Privilege Escalation at Scale
XM Cyber researchers detail a macOS privilege escalation technique that lets a standard user disable EDR/MDM agents without admin credentials by exploiting stale kernel CDHash trust caches combined with NIB payload injection to impersonate trusted, code-signed application components. Once inside the trusted process context, the attacker uses an AppleScript-to-JXA-to-Objective-C runtime bridge (loading OSAKit.framework, forging Block_layout/objc_msgSend structures) to call unauthenticated privileged XPC methods like runProcessWithCommand: and ceaseSystemExtensionWithReply:, forcing security products to disable or remove themselves. The authors built an open-source scanner, XPC Hunter, to find this exposure across installed macOS apps at scale and recommend fixing it via xpc_connection_set_peer_code_signing_requirement() or SecCodeCheckValidity() peer validation.
What it is
A macOS local privilege escalation / EDR-tamper technique from XM Cyber (via CrowdStrike) letting any standard, non-root user invoke privileged XPC methods with zero authentication, forcing security agents to disable or remove themselves. The accompanying scanner, XPC Hunter, is not yet released — it is slated to be presented and made available at Black Hat US in August 2026. CrowdStrike states its Falcon sensor already has detections and preventions in place.
How it works
The kernel's CDHash cache persists after a legitimately signed binary first executes. The attacker launches the signed app to populate that cache, then manipulates the on-disk bundle to inject a malicious NIB (Interface Builder) payload. Because the kernel trust cache still validates the process context, the injected code runs inside the trusted, signed component's memory and inherits its ability to talk to the root daemon unauthenticated.
NIB execution normally can't do pointer work, so the payload bridges out: AppleScript dynamically loads OSAKit.framework, transitions to JXA for Objective-C bridge access, then reaches malloc/free, dispatch_block_create, and raw objc_msgSend — enough to forge Block_layout structures and _Block_signature type encodings to satisfy NSXPC's validation-heavy serialization. It then enumerates exposed daemon methods and calls them.
Privileged methods the research surfaced include runProcessWithCommand:, terminateAppsAndAgents:, and ceaseSystemExtensionWithReply: (the summary omits terminateAppsAndAgents:).
Preconditions / Affected
Standard (non-root) local account; an installed app whose signed component populates the CDHash cache and whose root daemon exposes an XPC Mach service that trusts only CDHash. No admin credentials, kernel exploit, or memory-corruption bug required — the page stresses near-zero forensic trace and no exploit-signature triggering, since it abuses legitimate OS behavior.
What to do
Validate client identity inside the listener protocol, not via passive kernel-cache CDHash. Either:
xpc_connection_set_peer_code_signing_requirement()— note this was introduced in macOS 13, so it is unavailable on older systems.- Re-validate the on-disk signature with
SecCodeCheckValidity(), obtaining the peer viaSecCodeCopyGuestWithAttributes()paired with the incoming connection's native audit token.
Both break the impersonation primitive at the handshake, before any protocol method is exposed.
flowchart TD
A[Launch signed binary] --> B[Populate kernel CDHash cache]
B --> C[Inject malicious NIB]
C --> D{Peer validated at handshake?}
D -->|No, CDHash only| E[Trusted context: call privileged XPC]
D -->|Yes, set_peer_code_signing / SecCodeCheckValidity| F[Connection rejected]
E --> G[Agent disables/removes itself]Technologies named here
Techniques named here
- CDHash kernel cache exploitation
- NIB payload injection
- XPC trust boundary bypass / privileged method impersonation
- AppleScript-to-JXA runtime bridging
- Block_layout / _Block_signature spoofing
Related in Offensive Security