Documentation
Complete guide to configuring ClearanceKit's file access policies, app protections, jail rules, process ancestry, allowlists, and MDM deployment.
Setup
After dragging ClearanceKit to your Applications folder, open it and navigate to the Setup tab in the sidebar. Two steps are required:
- Activate the system extension — click Activate Extension. macOS will prompt you to allow the extension in System Settings. This is a one-time approval.
- Grant Full Disk Access — Endpoint Security requires Full Disk Access for the
opfiltersystem extension. Click the link in the Setup tab to open System Settings → Privacy & Security → Full Disk Access, and enableopfilter.
The Setup tab shows real-time connection status. A green indicator means the GUI is connected to the system extension via XPC. If it shows red, click Resync.
Extension lifecycle
The system extension runs independently of the GUI app. Closing the GUI does not stop enforcement. To update the extension after installing a new version of ClearanceKit, open Setup and click Update Extension. If jail rules are active, a warning dialog lists all currently jailed processes and explains that enforcement will pause briefly during the update.
Typical workflow
A typical workflow for protecting an application's data:
- Enable a built-in preset — navigate to App Protections and toggle on a preset such as Safari, Signal, or Messages. This immediately protects that app's data directories with curated rules.
- Monitor denied events — switch to the Events tab. Any process denied access to a protected path appears here in real time. Denied events also appear as inline notifications in your terminal.
- Refine policy — if a legitimate process is denied, expand the event row and click its code signature to add it to the allowlist, or create a more specific policy rule.
- Add custom protections — for apps without a built-in preset, click Add Application in App Protections. ClearanceKit auto-detects sandbox containers or runs a 60-second discovery session to capture the paths the app accesses.
- Confine risky processes — use Jail rules to restrict processes like package managers to a specific set of path prefixes. Any access outside the allowed set is denied regardless of other policy.
Events
The Events tab shows a live feed of file access events processed by the system extension.
Toolbar controls
- Filter — toggle between All, Allow, and Deny to focus on the events you care about.
- Show default allows — when off (the default), events that matched no rule and were allowed by default are hidden. Turn this on to see all traffic.
- Load History — fetch buffered events from the system extension. Useful if the GUI was closed and you want to review what happened.
- Clear — clear all events from the list.
Event details
Each event row shows the file path, the decision (allowed or denied), a timestamp, and the operation type if it is not a file open (rename, unlink, create, truncate, copy, readdir, link, exchangedata, or clone). Click a row to expand it and see:
- Source app — the app protection or rule that evaluated this event, with its protected path prefix.
- Process details — PID, executable path, Team ID, and Signing ID of the process that triggered the access.
- Ancestor chain — the full process ancestry tree, showing each ancestor's path and code signature. This lets you trace exactly how the process was launched.
Inline allowlisting
When viewing an expanded denied event, code signatures for the process and its ancestors appear as clickable links. Clicking a signature opens a dialog to add it to the global allowlist or as an allowed process for the relevant rule. This is the fastest way to build policy from observed behaviour.
Baseline and managed events
Events matched by baseline (built-in Apple process) or managed (MDM-delivered) rules are collapsed into compact rows with a baseline or managed badge. Expand them to see the full decision context.
Processes
The Processes tab provides two views of active enforcement:
Jailed Processes
A hierarchical tree of all processes currently confined by jail rules. Each entry shows:
- A green dot for active processes, grey for inactive.
- The process name, executable path, and the jail rule it matched.
- Child processes that inherited the jail from their parent.
- A count of denied accesses, expandable to see the specific paths. Click the + button on a denied path to add it to the jail rule's allowed paths.
Denied Processes
Processes grouped by signing identity that have been denied file access by policy rules. Each group shows the process name, Team ID, Signing ID, and event count. Expand a group to see individual denied events. Click the + button to add the process to the global allowlist.
Use Clear Inactive in the toolbar to remove entries for processes that have exited.
Process Tree
A searchable, sortable table of every running process known to the system extension. Columns include PID, PPID, process name, executable path, Signing ID, Team ID, UID, and GID. Search by any of these fields.
Creating rules from the Process Tree
Click any process row to open a wizard sheet with three options:
- Policy Rule — create a file access policy rule using this process's code signature.
- Jail Rule — create a jail rule confining this process to specific path prefixes.
- App Protection — if the process belongs to an app bundle, create an app protection with auto-detected paths. If no paths can be auto-detected, a discovery session starts.
Metrics
Real-time performance dashboard for the system extension's event pipeline.
Gauges
Five gauges show 10-second rolling averages and peak rates:
- Simple events/sec — events resolved on the fast path (no ancestry needed).
- Ancestry events/sec — events that required process ancestry lookup.
- Drops/sec — events dropped due to queue pressure (auto-allowed to meet kernel deadline).
- Jail events/sec — events evaluated against jail rules.
- Jail denies/sec — jail events that were denied.
Time series chart
A 60-second rolling chart plots events per second for each category, letting you correlate spikes in file access with specific activity on your machine.
Policy rules
Policy rules are the core building block of ClearanceKit. Each rule protects a path prefix and specifies which processes are allowed to access files under it.
Rule tiers
| Tier | Source | Editable |
|---|---|---|
| baseline | Compiled into the app | No |
| managed | Delivered via MDM configuration profile | No |
| User | Created in the GUI | Yes |
All tiers are active simultaneously. Rules are evaluated in merged order; the first matching rule determines the outcome.
Rule fields
| Field | Description |
|---|---|
protectedPathPrefix | The path pattern to protect. Supports wildcards. Any file access under this prefix triggers policy evaluation. |
allowedProcessPaths | Exact executable paths that are allowed. No wildcards. |
allowedSignatures | Code signatures (Team ID + Signing ID) that are allowed. |
allowedAncestorProcessPaths | If any ancestor in the process chain has this exact executable path, access is allowed. |
allowedAncestorSignatures | If any ancestor has a matching code signature, access is allowed. |
If all allowed* fields are empty, only processes on the global allowlist can access files under the protected path — every other process is denied. If a file matches the protected path and at least one criterion is defined, but no criterion matches the process, access is denied.
Creating a rule
- Navigate to Policy in the sidebar.
- Click Add Rule.
- Enter the protected path prefix (e.g.
/Users/*/Library/Safari). - Add allowed processes by typing signatures manually or clicking Pick from running processes to select from the live process list.
- Optionally add ancestor criteria (see process ancestry).
- Click Save. Touch ID is required.
Importing and exporting rules
The Policy tab toolbar has Import Rules and Export Rules buttons. Rules are serialised as JSON. This lets you share rule sets between machines without MDM, or back up your configuration.
App Protections
App Protections group related policy rules under a named application. Instead of managing individual rules, you enable or disable protection for an entire app with a single toggle.
Enabling a preset
Navigate to App Protections. The Built-in section lists all presets. Toggle any preset on to immediately protect that app's data. Touch ID is required.
If a preset shows update available, its active rules have drifted from the built-in definition — either because a newer version of ClearanceKit ships updated rules, or because you have modified the preset's rules manually. Click Update to reset the preset to the current built-in definition, or use Update All in the toolbar.
Adding a custom app protection
- Click Add Application (or drag an
.appfrom Finder onto the list). - Select the application from the picker.
- If ClearanceKit can auto-detect the app's data paths (via sandbox containers and app groups), rules are generated immediately.
- If not, a discovery session starts.
Discovery sessions
When ClearanceKit cannot auto-detect an app's file paths, a 60-second discovery session begins. During this session:
- Close and reopen the target application.
- ClearanceKit captures every directory path the app accesses.
- Captured paths appear in real time in the discovery panel.
- Click Review to inspect the captured paths.
In the review screen, you can remove paths that should not be protected and add allowed processes for each path. Click Create Protection to save.
Editing an app protection
Click the edit button on any custom app protection to modify its protected paths, add or remove allowed process signatures, or delete individual path entries.
Built-in presets
ClearanceKit ships with curated presets for popular applications. Each preset protects the app's local data directories and allows only the app's own processes (identified by code signature) to access them.
| Preset | Protected paths | Rules |
|---|---|---|
| Safari |
~/Library/Safari~/Library/Containers/com.apple.Safari~/Library/Group Containers/group.com.apple.safari
|
3 |
~/Library/Mail~/Library/Containers/com.apple.mail~/Library/Group Containers/group.com.apple.mail.shared
|
3 | |
| Messages | ~/Library/Messages |
1 |
| Contacts |
~/Library/Application Support/AddressBook~/Library/Containers/com.apple.AddressBook
|
2 |
| Notes | ~/Library/Group Containers/group.com.apple.notes |
1 |
| Signal | ~/Library/Application Support/Signal |
1 |
| Slack |
~/Library/Application Support/Slack~/Library/Caches/com.tinyspeck.slackmacgap
|
2 |
| Discord |
~/Library/Application Support/discord~/Library/Caches/com.hnc.Discord~/Library/Caches/com.hnc.Discord.ShipIt
|
3 |
| Chrome |
~/Library/Application Support/Google~/Library/Caches/Google
|
2 |
| HEY | ~/Library/Application Support/HEY |
1 |
| Mullvad VPN | ~/Library/Application Support/Mullvad VPN |
1 |
Path notation
Paths shown as ~/Library/... are stored as /Users/*/Library/... in the actual rules, using the * wildcard to match any username.
Each preset allows access only to processes signed by the app's developer. For example, the Safari preset allows apple:com.apple.Safari, apple:com.apple.WebKit.WebContent, apple:com.apple.Safari.History, and other Apple-signed Safari components. A trojanised binary or unrelated process attempting to read Safari's cookies will be denied.
Jail rules
Jail rules confine a process to a specific set of path prefixes. Unlike policy rules (which protect specific paths from unauthorised processes), jail rules restrict where a jailed process can access anything at all. Any file access outside the allowed set is denied, regardless of other policy rules.
How jails work
- A jail rule matches a process by its exact code signature (Team ID + Signing ID).
- When a matched process attempts to access a file, the path is checked against the rule's allowed path prefixes.
- If the path matches any allowed prefix, access is granted. Otherwise it is denied.
- Child processes inherit their parent's jail. If a jailed process spawns a child, the child is also confined to the same allowed paths.
Wildcards are not supported in jail signatures
The jailed process signature must be exact. You cannot use * as the Signing ID in a jail rule. Wildcards are supported in the allowed path prefixes.
Creating a jail rule
- Navigate to Jail in the sidebar.
- Click Add Jail Rule.
- Enter a name for the rule.
- Enter the jailed process signature, or click Pick to select from running processes.
- Add allowed path prefixes. See jail wildcard patterns for supported syntax.
- Click Save. Touch ID is required.
Jail wildcard patterns
Allowed path prefixes in jail rules support three wildcard patterns:
| Pattern | Meaning | Example |
|---|---|---|
* |
Matches any single path component (does not cross /) |
/Users/*/Documents matches /Users/alice/Documents |
** |
Matches zero or more path components at any depth | /tmp/** matches /tmp/foo/bar/baz |
*** |
Matches any characters within a single path component (suffix/prefix matching) | /dev/ttys*** matches /dev/ttys001, /dev/ttysA |
Importing and exporting jail rules
The Jail tab has an Import / Export button. Select which rules to export, then save as JSON. Import rules from a JSON file on another machine.
Allowlist
The global allowlist is a list of processes that bypass all policy rules entirely. Any process matching an allowlist entry is allowed to access any file, regardless of policy rules or jail rules.
Allowlist tiers
| Tier | Source | Editable |
|---|---|---|
| baseline | 34 essential Apple system processes (Finder, Spotlight, apfsd, etc.) compiled into the app | No |
| managed | Delivered via MDM configuration profile | No |
| User | Created in the GUI | Yes |
In addition to the compiled baseline, ClearanceKit automatically discovers XProtect remediator executables at startup and adds them to the allowlist. It also monitors for XProtect updates and refreshes the allowlist entries to ensure Apple's malware remediation is never impeded.
Entry types
Each allowlist entry matches by one of two criteria:
- Signing ID — matches any process with that code signature. Optionally constrained by Team ID. Supports
*as the Signing ID to match any app from a specific team. - Process path — matches only the exact executable path. No wildcards, no prefix matching.
An entry can also be marked as Platform Binary, which restricts it to Apple-signed binaries only.
Ancestor allowlist
In addition to the regular allowlist, ClearanceKit supports ancestor allowlist entries. These match against any process in the calling chain, not just the immediate process. If any ancestor matches, the immediate process bypasses all policy rules.
This is useful for:
- MDM agents that spawn helper tools
- Security products that launch remediation binaries
- CI runners that invoke build tools
Add ancestor entries via the Add Ancestor Entry button in the Allowlist toolbar.
Security products and network monitors
If you run other endpoint security or network monitoring tools alongside ClearanceKit, add them to the global allowlist. These products need to inspect files across the entire file system to function correctly, and ClearanceKit's policy rules will otherwise block them from reading protected paths.
Add your security tools to the allowlist
Without an allowlist entry, security products will be denied access to files in protected directories, which may prevent them from detecting threats or monitoring network connections associated with those files.
Common examples:
| Product | Signing ID | Team ID |
|---|---|---|
| BlockBlock | com.objective-see.blockblock | VBG97UB4TA |
| Little Snitch Network Monitor | at.obdev.littlesnitch.networkmonitor | MLZF7K7B5R |
To add one of these, navigate to Allowlist, click Add Entry, select Signing ID, enter the Signing ID and Team ID from the table above, and save. You can also use the Pick from running processes button to find other security products running on your machine and add them directly.
Wildcard patterns
Different parts of ClearanceKit support different wildcard syntax. This table summarises what is available where.
Policy rule protected paths
The protectedPathPrefix field supports glob-style wildcards:
| Pattern | Meaning | Example |
|---|---|---|
* |
Any characters within a single path component | /Users/*/Library/Safari matches /Users/alice/Library/Safari/Cookies.db |
** |
Zero or more path components at any depth | /Users/**/secrets matches /Users/alice/projects/secrets |
? |
Any single character within a component | /data/v?/file matches /data/v1/file but not /data/v12/file |
Component-boundary matching
Paths without wildcards are matched as prefixes at component boundaries. /Library/App/clearancekit matches /Library/App/clearancekit/store.db but does not match /Library/App/clearancekit-extra/file. The match stops at the / separator.
Allowed process paths
The allowedProcessPaths and allowedAncestorProcessPaths fields require exact matches. No wildcards or prefix matching is supported.
Code signatures
The allowedSignatures and allowedAncestorSignatures fields support a single wildcard:
*as the Signing ID matches any app from the specified Team ID. For example,EQHXZ8M8AV:*matches any Google-signed binary.- No partial wildcarding (e.g.
com.example.*) is supported; it would be treated as a literal string. - Team ID must always be exact.
Jail allowed paths
See jail wildcard patterns above. Jail rules support *, **, and the additional *** (intra-component match).
Allowlist process paths
Allowlist entries that match by process path require an exact match. No wildcards.
Allowlist signing IDs
Allowlist entries that match by Signing ID support * to match any Signing ID from a given Team ID, identical to policy rule signatures.
Summary table
| Context | * | ** | ? | *** | Prefix | Exact |
|---|---|---|---|---|---|---|
| Policy protected path | Yes | Yes | Yes | No | Yes | Yes |
| Policy allowed process path | No | No | No | No | No | Yes |
| Policy signature (Signing ID) | Yes (* only) | No | No | No | No | Yes |
| Jail allowed path | Yes | Yes | No | Yes | Yes | Yes |
| Jail signature | No | No | No | No | No | Yes |
| Allowlist process path | No | No | No | No | No | Yes |
| Allowlist Signing ID | Yes (* only) | No | No | No | No | Yes |
Code signatures
ClearanceKit identifies processes by their macOS code signature, which consists of two parts:
- Team ID — the Apple Developer ID certificate used to sign the binary (e.g.
EQHXZ8M8AVfor Google,U68MSDN6DRfor Signal). Apple platform binaries useappleas their Team ID. - Signing ID — the bundle identifier or binary name embedded in the signature (e.g.
com.apple.Safari,org.whispersystems.signal-desktop).
Signatures are written in teamID:signingID format. For example:
apple:com.apple.Safari # Safari
EQHXZ8M8AV:com.google.Chrome # Google Chrome
U68MSDN6DR:org.whispersystems.signal-desktop # Signal
53Q6R32WPB:com.hnc.Discord # Discord
EQHXZ8M8AV:* # Any Google-signed binary
Code signatures cannot be spoofed without access to the developer's private signing key. A trojanised replacement binary carries a different signature (or no valid signature at all) and is immediately denied. Unlike file hashes, signatures remain valid across all future updates from the same developer.
Process ancestry
ClearanceKit maintains a live, in-memory tree of every running process with cached ancestor chains. This lets policy rules make decisions based not just on who is accessing a file, but on who launched them.
Why ancestry matters
Many legitimate workflows involve generic system tools — cp, ditto, shove — that access protected paths on behalf of a trusted parent process. App updaters use these tools to replace application bundles. Anti-malware software and MDM agents spawn them to perform remediation or policy enforcement. Without ancestry, you would need to globally allowlist these tools (weakening your policy) or ask every vendor to change their update mechanism.
With ancestry, you can allow these tools to work only when launched by a trusted parent, without any changes from the vendor:
- Allow
dittoandcpto write to a protected app's data directory only when their ancestor chain includes the app's own updater, signed by the app vendor. - Allow MDM agent helper tools to access protected paths only when spawned by the MDM agent itself.
- Allow anti-malware remediation tools to access any protected path only when launched by the security product's signed parent process.
How ancestry is evaluated
When a policy rule has allowedAncestorProcessPaths or allowedAncestorSignatures set, ClearanceKit walks the process's ancestor chain (parent, grandparent, and so on) looking for a match. If any ancestor matches, the access is allowed.
Ancestry evaluation is lazy. The system extension classifies each event into one of three categories:
- No rule applies — the path is not protected. No ancestry needed. Immediate allow.
- Process-level only — a rule matches but has no ancestor criteria. Evaluate using only the immediate process's identity.
- Ancestry required — a rule has ancestor criteria. Fetch the ancestor chain and evaluate.
This means ancestry lookup (which is more expensive) only happens when a rule actually requires it.
Performance note
Rules with ancestor criteria require the system extension to look up the process tree and may add latency compared to process-level-only rules. The GUI warns you about this when adding ancestor criteria to a rule. For most workloads this is imperceptible, but avoid adding ancestry criteria to rules that match very high-frequency paths.
Ancestor information
Each ancestor record includes:
- Executable path
- Team ID and Signing ID
- User ID (UID) and Group ID (GID)
The ancestor chain is visible in the Events tab when you expand an event row, shown as a tree structure from the immediate parent up to the root process.
Policy evaluation order
When a process attempts to access a file, ClearanceKit evaluates policy in this order. The first match wins.
- Global allowlist — if the process matches any allowlist entry (baseline, managed, or user), access is allowed immediately. All policy rules are bypassed.
- Ancestor allowlist — if any ancestor of the process matches an ancestor allowlist entry, access is allowed immediately.
- Policy rules (merged: baseline + managed + user) — the file path is checked against each rule's protected path prefix. For the first matching rule:
- Check the process's executable path against
allowedProcessPaths. - Check the process's code signature against
allowedSignatures. - Check ancestor executable paths against
allowedAncestorProcessPaths. - Check ancestor code signatures against
allowedAncestorSignatures. - If any criterion matches: allowed.
- If no criterion matches: denied.
- Check the process's executable path against
- No rule applies — if no rule's protected path prefix matches the file, access is allowed by default.
Jail rules are evaluated by a separate, dedicated Endpoint Security client and operate independently of the above. A process confined by a jail rule is denied access to any path outside the jail's allowed set, regardless of policy rules.
Touch ID
All policy mutations — creating, editing, or deleting rules, allowlist entries, jail rules, and app protections — require Touch ID authentication. This prevents malware from programmatically modifying your policy to grant itself access.
The user policy database is also cryptographically signed. If the signature is invalid on load (indicating potential tampering), ClearanceKit shows a dialog listing the suspect entries. You can choose to:
- Approve & Sign — accept the current data and re-sign it (requires Touch ID).
- Clear Database — delete all user-created rules and allowlist entries and start fresh.
MDM deployment
ClearanceKit supports enterprise deployment via Apple Configuration Profiles (mobileconfig). Managed policies are read from the uk.craigbass.clearancekit preferences domain and can be delivered by any MDM that supports managed preferences (Jamf, Kandji, Mosyle, etc.).
Preference keys
| Key | Type | Description |
|---|---|---|
FAAPolicy | Array | File access policy rules |
GlobalAllowlist | Array | Global allowlist entries |
JailRules | Array | Jail rules |
AppProtections | Array | App protection groupings (for GUI display) |
FAAPolicy schema
Each entry in the FAAPolicy array:
{
"ID": "optional-uuid-string",
"ProtectedPathPrefix": "/Users/*/Library/Safari",
"AllowedProcessPaths": ["/usr/bin/example"],
"AllowedSignatures": ["apple:com.apple.Safari", "TEAM:*"],
"AllowedAncestorProcessPaths": ["/usr/bin/parent"],
"AllowedAncestorSignatures": ["TEAM:com.example.runner"],
"EnforceOnWriteOnly": false
}
If ID is omitted, it is derived deterministically from the ProtectedPathPrefix.
When EnforceOnWriteOnly is true, the rule only fires for write operations (rename, unlink, link, create, truncate, copyfile, exchangedata, clone, and opens with FWRITE / O_APPEND / O_TRUNC). Read-only opens fall through to the next rule. Use this for tamper-protection of config files like /etc/pam.d, /etc/ssh, or audio plugin bundles, where any process should be able to read the file but only specific processes should be able to modify it. Defaults to false.
GlobalAllowlist schema
{
"ID": "optional-uuid-string",
"SigningID": "com.example.app",
"ProcessPath": "",
"PlatformBinary": false,
"TeamID": "EQHXZ8M8AV"
}
Match by SigningID or ProcessPath (not both). If PlatformBinary is true, only Apple-signed binaries match.
JailRules schema
{
"ID": "optional-uuid-string",
"Name": "Confine Node.js",
"JailedSignature": "TEAM:com.nodejs.node",
"AllowedPathPrefixes": ["/tmp/**", "/Users/*/Projects/**"]
}
The JailedSignature must be exact (no wildcards). Name is required and displayed in the GUI.
AppProtections schema
{
"ID": "optional-uuid-string",
"AppName": "Safari",
"BundleID": "com.apple.Safari",
"RuleIDs": ["uuid-of-rule-1", "uuid-of-rule-2"]
}
RuleIDs must reference IDs of rules defined in the FAAPolicy array.
Profile structure
The preferences must be delivered inside a com.apple.ManagedClient.preferences payload targeting the uk.craigbass.clearancekit domain. See the GitHub repository for a complete example mobileconfig file.
Managed rules appear in the GUI with a managed badge and cannot be edited or deleted by the end user.
Exporting policies
ClearanceKit can export policies as Apple Configuration Profiles for deployment to other machines.
Export as ClearanceKit mobileconfig
Navigate to the ClearanceKit (.mobileconfig) export tab. A three-step wizard lets you select:
- Policy — which rule tiers and app protections to include.
- Enforcement — which jail rules and allowlist entries to include.
- Review — summary of the export with warnings if protections reference rules not included in the export.
Export as Santa FileAccessPolicy
Navigate to the Santa export tab. This generates a Santa-compatible mobileconfig from your ClearanceKit rules. The wizard warns you about two limitations:
- Ancestry rules — Santa has no equivalent of process ancestry. Rules with ancestor criteria are flagged.
- Jail rules — Santa does not confine subprocesses. Jail rules are exported as file access rules, but child-process confinement is lost.
MCP agents
ClearanceKit includes an optional Model Context Protocol (MCP) server that allows AI coding agents to query policy state. This is disabled by default.
Enabling MCP
Navigate to MCP Agents in the sidebar and toggle the server on. A security warning explains that this increases the attack surface. Disable the server when not in use.
Connected agents
The MCP Agents tab shows all connected agents with their client name, version, connection time, and tool call count. Click Revoke to disconnect an agent.
The MCP socket path is displayed in the toolbar for configuring your AI agent's connection.