
Build the uninstaller first
A security agent that will not uninstall cleanly can turn one swap into a fleet-wide cleanup problem.
Replacing a macOS security agent means removing more than its app bundle: system extensions, PPPC profiles, and launch daemons can remain after the app is gone.
Eventually, something forces a swap. A contract ends. The product stops fitting the environment. Or a new agent conflicts with the one already installed. On macOS, taking the old one off is the hard half of the job.
I've seen teams get this backwards. They validate the install, watch the agent check in green across the fleet, and call it done. Removal is a one-line script for later.
Then later shows up mid-incident. The agent I deployed turned out to be four moving parts: a system extension, a PPPC profile for TCC grants, launch daemons, and an app bundle. Those pieces had to come apart in the right order.
The teardown has four parts
Delete the app from a script and the extension can remain active. Remove an allow profile and Apple's payload schema says an active extension deactivates; that still is not a complete uninstall. A leftover extension can block its own reinstall.
Apple's RemovableSystemExtensions key lets an app request deactivation of its own extension without local administrator authorization. Apple's documentation covers that deactivation step. It does not cover cleaning up the rest of the agent.
The PPPC payload is its own removal concern. The macOS 27 PPPC guide explains why a legacy profile still carries Full Disk Access and Screen Recording even as some privacy defaults move elsewhere. A system-extension agent needs its teardown tested against the payloads it actually received, not just its app bundle.
Before the first production Mac got the new agent, I built and proved the teardown.
- Validated a clean uninstall on a real device before any production machine was touched: a system-extension deactivation request, a restart-state check, dependency-ordered component removal, and a check that no extension stayed registered.
- Made both install and removal run without user interaction, so rollout day did not turn into a fleet's worth of approval prompts and help-desk tickets.
- Staged it through Jamf Pro as test scope, then soak, then broad, with the tested rollback behind every ring.
Prove the rollback before rollout
Proving removal before trusting the deploy is the belt-and-suspenders habit applied to a rollout. Confirm the retreat path works before you need it, not while hundreds of Macs are waiting on you.
The honest cost: building the uninstaller first is slower up front. You spend real hours on a path you hope to never run. That time is insurance. You pay it once now, calmly, instead of during an incident, with an agent you cannot remove and a replacement you cannot cleanly put in its place.
The rollout itself was boring. Green check-ins, no ticket flood, and a rollback I had already run for real. Boring was the goal. Boring means I handled the failure modes before they went live.
The same discipline matters when an endpoint tool becomes the incident itself. CrashStealer's user-session chain is a different problem, but the response still depends on knowing which agent components and access grants are present before a cleanup starts.
Anyone can push software to a large fleet. Taking it cleanly back off is what separates a deployment from a gamble.
So when you roll out an endpoint agent: do you prove the uninstall first, or find out you needed it the hard way, one stuck system extension at a time?
Sources
Sources preserved from the verified publication package. Recheck vendor and community guidance before relying on it in a new rollout:
- Apple Developer: System Extensions
- Apple Developer: OSSystemExtensionRequest deactivation request
- Apple device-management schema: System Extensions payload policy
- Apple Deployment Guide: System extensions in macOS
- Microsoft: Troubleshoot performance issues for Defender for Endpoint on macOS
- Microsoft: System extensions for Defender for Endpoint on macOS
- Broadcom: Existing system extension prevents Carbon Black install or upgrade
- Graham Pugh: Delete a system extension from the command line
- Der Flounder: Uninstalling macOS system extensions
- Der Flounder: Silently uninstalling system extensions on macOS Monterey and earlier
- Jamf Nation: Uninstall system extensions without user approval
- Jamf: System extension changes in Sequoia