> For the complete documentation index, see [llms.txt](https://newdocs.keeper.io/en/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://newdocs.keeper.io/en/keeperpam/endpoint-privilege-manager/deployment/deploy-with-macos/macos-system-extension-configuration.md).

# System Extension Configuration

<figure><img src="/files/K0reF02jsycC3nuVWCrg" alt=""><figcaption></figcaption></figure>

The macOS System Extension (`KeeperSystemExtension`) is the user-space component that gives KEPM visibility into privilege elevation requests, command-line invocations, and package installations on macOS. It uses Apple's Endpoint Security Framework to intercept authorization petitions — the same mechanism macOS uses for UAC-like elevation prompts — and routes them through the KEPM policy engine before allowing or denying them.

This page covers what the System Extension is, the identifiers and entitlements MDM administrators need to allowlist it, how to configure it, and how to troubleshoot common issues.

***

## Identifiers and Code Signing

KEPM's macOS components are signed and distributed by Keeper Security. The values below are required for any MDM-managed allowlisting, PPPC profile, or System Extension policy.

<table><thead><tr><th width="267.33331298828125">Property</th><th>Value</th></tr></thead><tbody><tr><td>App name</td><td><code>Keeper Endpoint Privilege Manager.app</code></td></tr><tr><td>App bundle ID</td><td><code>com.keeper.endpoint-privilege-manager</code></td></tr><tr><td>App install path</td><td><code>/Applications/Keeper/Keeper Endpoint Privilege Manager.app</code></td></tr><tr><td>System Extension name</td><td><code>com.keeper.keeper-privilege-manager.monitor.systemextension</code></td></tr><tr><td>System Extension bundle ID</td><td><code>com.keeper.keeper-privilege-manager.monitor</code></td></tr><tr><td>System Extension binary path</td><td><code>/Applications/Keeper/Keeper Endpoint Privilege Manager.app/Contents/Library/SystemExtensions/com.keeper.keeper-privilege-manager.monitor.systemextension/Contents/MacOS/com.keeper.keeper-privilege-manager.monitor</code></td></tr><tr><td>System Extension type</td><td><code>EndpointSecurityExtension</code></td></tr><tr><td>Notification helper bundle ID</td><td><code>com.keeper.keepernotify</code></td></tr><tr><td>Apple Developer Team ID</td><td><code>234QNB7GCA</code> (verifiable on any installed Mac with <code>codesign -dv "/Applications/Keeper/Keeper Endpoint Privilege Manager.app"</code>)</td></tr><tr><td>Signing Authority</td><td><code>Developer ID Application: Callpod Inc. (234QNB7GCA)</code></td></tr><tr><td>Runtime identifier (in <code>systemextensionsctl list</code>)</td><td><code>com.keeper.keeper-privilege-manager.monitor</code></td></tr><tr><td>Code requirement (extension)</td><td><code>anchor apple generic and identifier "com.keeper.keeper-privilege-manager.monitor" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "234QNB7GCA")</code></td></tr><tr><td>Code requirement (app)</td><td><code>anchor apple generic and identifier "com.keeper.endpoint-privilege-manager" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "234QNB7GCA")</code></td></tr><tr><td>Code requirement (notification helper)</td><td><code>anchor apple generic and identifier "com.keeper.keepernotify" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "234QNB7GCA")</code></td></tr></tbody></table>

{% hint style="info" %}
**Why "Callpod Inc."?** Keeper Security is a wholly-owned subsidiary of Callpod Inc. Apple requires Developer ID certificates to be issued to the parent legal entity, so the signing Authority string reads `Callpod Inc.` rather than `Keeper Security, Inc.` This is expected — do not flag profiles with this Authority string as suspicious.

**Why does each component have its own bundle ID?** Each Keeper macOS component (app, extension, notification helper, and any plugins) is signed with a distinct bundle ID under the `com.keeper.*` namespace so they can be allowlisted, audited, and controlled independently.
{% endhint %}

## How it Works

When a user attempts to run a command with `sudo`, install a `.pkg` file, or trigger any other authorization petition on a managed Mac, the System Extension intercepts the request before macOS processes it. It sends the request to the KEPM policy engine via the internal MQTT broker, waits for a policy decision, and responds accordingly — allowing, denying, or triggering a control flow (justification, MFA, or approval).

For `.dmg` disk image opens, the System Extension coalesces burst events: regardless of how many open events macOS generates for the same file, the user sees exactly one policy prompt and the agent processes exactly one policy request per mount operation.

The System Extension runs in user space (not the kernel) using Apple's Endpoint Security Framework, and requires explicit user approval — or MDM pre-approval — before it can be activated.

**Why the app installs under `/Applications/Keeper/` rather than `/Library/Keeper/`:** Apple's [System Extensions and Drivers documentation](https://developer.apple.com/documentation/systemextensions/installing-system-extensions-and-drivers) requires that "your app is installed in an appropriate Applications directory of the system" before the System Extension framework will allow activation. KEPM places the app under `/Applications/Keeper/` to satisfy this requirement. Supporting binaries that are not subject to this constraint (CLI tools, plugins, jobs, configuration) continue to live under `/Library/Keeper/`.

## MDM Deployment

A complete MDM rollout of KEPM requires three configuration profiles, deployed in order:

1. **System Extension allowlist** — pre-approves the extension so it activates silently on install.
2. **Full Disk Access (PPPC)** — grants the app and extension the file-system visibility needed to enforce policy.
3. **Notification permissions** *(recommended)* — allows KEPM to display elevation prompts and approval status.

Deploy the **System Extension allowlist before** installing the KEPM package. If the extension is installed before the allowlist profile is in place, the user will see a "System Extension Blocked" notification and the extension will enter the `[terminated waiting for user]` state until approved manually in System Settings or until an MDM profile arrives.

{% stepper %}
{% step %}

### System Extension Allowlist Profile

This profile uses Apple's `com.apple.system-extension-policy` payload to pre-approve KEPM's Endpoint Security extension.

```xml
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>PayloadType</key>
  <string>com.apple.system-extension-policy</string>
  <key>PayloadUUID</key>
  <string><!-- generate a UUID --></string>
  <key>PayloadIdentifier</key>
  <string>com.keeper.kepm.system-extension-policy</string>
  <key>PayloadVersion</key>
  <integer>1</integer>
  <key>PayloadDisplayName</key>
  <string>Keeper EPM — System Extension Allowlist</string>
  <key>AllowUserOverrides</key>
  <true/>
  <key>AllowedSystemExtensions</key>
  <dict>
    <key>234QNB7GCA</key>
    <array>
      <string>com.keeper.keeper-privilege-manager.monitor</string>
    </array>
  </dict>
  <key>AllowedSystemExtensionTypes</key>
  <dict>
    <key>234QNB7GCA</key>
    <array>
      <string>EndpointSecurityExtension</string>
    </array>
  </dict>
</dict>
</plist>
```

`AllowUserOverrides` is set to `true` so administrators can manually remove the extension during troubleshooting; set it to `false` to enforce strict policy and prevent local removal.
{% endstep %}

{% step %}

### Full Disk Access (PPPC)

The System Extension and the Keeper Endpoint Privilege Manager app both require Full Disk Access to monitor file operations and intercept authorization events.

**Interactive install:** When a user is logged in at the console, the installer automatically opens System Settings to the Full Disk Access pane and displays a floating alert listing the items that need approval:

* `Keeper Endpoint Privilege Manager` (`/Applications/Keeper/Keeper Endpoint Privilege Manager.app`)
* `com.keeper.keeper-privilege-manager.monitor` (the System Extension, shown by bundle ID)

**MDM / headless install:** When deployed via MDM (no interactive terminal), the installer skips the FDA dialog automatically. Grant Full Disk Access using the Privacy Preferences Policy Control payload below.

```xml
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>PayloadType</key>
  <string>com.apple.TCC.configuration-profile-policy</string>
  <key>PayloadUUID</key>
  <string><!-- generate a UUID --></string>
  <key>PayloadIdentifier</key>
  <string>com.keeper.kepm.pppc</string>
  <key>PayloadVersion</key>
  <integer>1</integer>
  <key>PayloadDisplayName</key>
  <string>Keeper EPM — Full Disk Access</string>
  <key>Services</key>
  <dict>
    <key>SystemPolicyAllFiles</key>
    <array>
      <dict>
        <key>Identifier</key>
        <string>com.keeper.keeper-privilege-manager.monitor</string>
        <key>IdentifierType</key>
        <string>bundleID</string>
        <key>CodeRequirement</key>
        <string>anchor apple generic and identifier "com.keeper.keeper-privilege-manager.monitor" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "234QNB7GCA")</string>
        <key>Allowed</key>
        <true/>
        <key>StaticCode</key>
        <false/>
      </dict>
      <dict>
        <key>Identifier</key>
        <string>com.keeper.endpoint-privilege-manager</string>
        <key>IdentifierType</key>
        <string>bundleID</string>
        <key>CodeRequirement</key>
        <string>anchor apple generic and identifier "com.keeper.endpoint-privilege-manager" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "234QNB7GCA")</string>
        <key>Allowed</key>
        <true/>
        <key>StaticCode</key>
        <false/>
      </dict>
    </array>
  </dict>
</dict>
</plist>
```

{% hint style="info" %}
The `certificate leaf[subject.OU] = "234QNB7GCA"` clause in `CodeRequirement` pins the profile to Keeper-signed binaries only. Without it, a non-Keeper binary registering the same bundle ID would inherit Full Disk Access — a real risk worth eliminating.
{% endhint %}
{% endstep %}

{% step %}

### Notification Permissions (recommended)

KEPM uses `KeeperNotify` — a Swift-based companion app — to display elevation prompts, approval results, and policy notifications in the macOS Notification Center. Without this profile, users may not see elevation prompts until they manually approve notifications in System Settings.

```xml
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>PayloadType</key>
  <string>com.apple.notificationsettings</string>
  <key>PayloadUUID</key>
  <string><!-- generate a UUID --></string>
  <key>PayloadIdentifier</key>
  <string>com.keeper.kepm.notifications</string>
  <key>PayloadVersion</key>
  <integer>1</integer>
  <key>PayloadDisplayName</key>
  <string>Keeper EPM — Notifications</string>
  <key>NotificationSettings</key>
  <array>
    <dict>
      <key>BundleIdentifier</key>
      <string>com.keeper.keepernotify</string>
      <key>NotificationsEnabled</key>
      <true/>
      <key>AlertType</key>
      <integer>2</integer>
      <key>BadgesEnabled</key>
      <true/>
      <key>SoundsEnabled</key>
      <true/>
      <key>CriticalAlertEnabled</key>
      <true/>
      <key>ShowInLockScreen</key>
      <false/>
      <key>ShowInNotificationCenter</key>
      <true/>
    </dict>
  </array>
</dict>
</plist>
```

`AlertType: 2` displays persistent alerts (banner that stays until dismissed), appropriate for elevation prompts that require user action. Use `1` for temporary banners if you prefer less intrusive notifications.
{% endstep %}
{% endstepper %}

## Verifying MDM Deployment

After all three profiles deploy and the KEPM package installs, verify on a target Mac:

```bash
# Confirm profiles are installed
profiles show -type configuration | grep -E "Keeper|kepm"

# Confirm extension is activated and enabled
systemextensionsctl list

# Confirm Full Disk Access is granted
sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" \
  "SELECT client, auth_value FROM access WHERE service='kTCCServiceSystemPolicyAllFiles';"
```

The extension should appear as `[activated enabled]`. `auth_value=2` in the TCC database means access is granted (`0`=denied, `1`=prompt, `2`=allowed).

## Configuration File

The System Extension is configured via `SystemExtension.json`. `KeeperPrivilegeManager` reads this file and serves its contents to the System Extension over HTTPS when the extension initializes or reconnects. The file is located at:

```
/Library/Keeper/sbin/Plugins/SystemExtension.json
```

Settings are structured as a nested JSON object under a top-level `"metadata"` key. The sections below show each setting using its full JSON path (e.g. `metadata.mqttOutages.connectionFailureBehavior`). All settings ship with defaults in the file; override only the values that need to differ from those defaults.

### MQTT Outage Behavior

If the System Extension loses its connection to the internal MQTT broker (which can happen briefly during service restarts), it falls back to a configurable behavior for pending authorization petitions. This is a deliberate fail-open default to prevent the machine from becoming unusable if the KEPM service is temporarily unavailable.

<table><thead><tr><th width="208.66668701171875">Setting</th><th width="97.33331298828125">Default</th><th>Description</th></tr></thead><tbody><tr><td><code>metadata.mqttOutages.connectionFailureBehavior</code></td><td><code>"allow"</code></td><td>What to do with authorization petitions during an MQTT outage: <code>"allow"</code> or <code>"deny"</code></td></tr><tr><td><code>metadata.mqttOutages.retries.minDelay</code></td><td><code>1</code></td><td>Minimum delay in seconds between reconnect attempts</td></tr><tr><td><code>metadata.mqttOutages.retries.maxDelay</code></td><td><code>20</code></td><td>Maximum delay in seconds between reconnect attempts (exponential backoff cap)</td></tr></tbody></table>

**Security note:** If your security posture requires fail-closed behavior (deny all during MQTT outages), set `connectionFailureBehavior` to `"deny"`. Be aware that this means any KEPM service interruption will block all privilege elevation on the affected Mac until the service is restored.

### Policy Response Timeout

If the policy engine does not respond to an authorization petition within the configured timeout, the System Extension falls back to a configurable action.

<table><thead><tr><th width="164.66668701171875">Setting</th><th width="98.66668701171875">Default</th><th>Description</th></tr></thead><tbody><tr><td><code>metadata.policy.maxResponseTimeout</code></td><td><code>5.0</code></td><td>Seconds to wait for a policy decision before applying the timeout action</td></tr><tr><td><code>metadata.policy.onPolicyTimeout</code></td><td><code>"allow"</code></td><td>Action on timeout: <code>"allow"</code> or <code>"deny"</code></td></tr></tbody></table>

The 5-second default is appropriate for most environments. For approval-gated workflows where a user must wait for a remote approver to respond, increase this value to match your expected approval latency — for example, `300` for a 5-minute approval window. Be aware that setting this too high will cause elevation requests to hang for the full duration if the policy engine is unavailable.

### Policy Response Cache

The extension caches policy responses to avoid re-evaluating repeated identical requests within a short window.

<table><thead><tr><th width="212">Setting</th><th width="97.3333740234375">Default</th><th>Description</th></tr></thead><tbody><tr><td><code>metadata.policy.cache.cleanupInterval</code></td><td><code>30</code></td><td>How often (in minutes) the cache sweeps and removes expired entries</td></tr><tr><td><code>metadata.policy.cache.expireAfter</code></td><td><code>60</code></td><td>How long (in seconds) a cached policy response remains valid</td></tr></tbody></table>

### High-Load Relief

When the policy engine is saturated and stops responding promptly, the extension can automatically allow requests from known-safe system paths rather than queuing them behind overloaded policy evaluation.

<table><thead><tr><th width="239.33331298828125">Setting</th><th width="114.6666259765625">Default</th><th>Description</th></tr></thead><tbody><tr><td><code>metadata.policy.highLoad.inflightThreshold</code></td><td><code>200</code></td><td>Number of concurrent in-flight policy requests at which high-load relief engages</td></tr><tr><td><code>metadata.policy.highLoad.fallbackAllowPaths</code></td><td><em>(see below)</em></td><td>Paths auto-allowed while the threshold is exceeded</td></tr></tbody></table>

The default `fallbackAllowPaths` covers standard macOS system locations:

```json
[
  "/System/Library/PrivateFrameworks",
  "/usr/libexec",
  "/System/Library/CoreServices",
  "/System/Library/Frameworks",
  "/System/Applications",
  "/usr/bin",
  "/usr/sbin",
  "/Library/Keeper"
]
```

Only modify this list if you have tested the impact. Removing system paths from the fallback list under sustained high load may cause system processes to be delayed or denied.

### Path Allow-Lists

The System Extension uses allow-lists to identify activity that should pass through without a full policy round-trip — typically Keeper's own binaries and well-known macOS system paths that do not require monitoring.

<table><thead><tr><th width="348.66668701171875">Setting</th><th>Description</th></tr></thead><tbody><tr><td><code>metadata.fileAccess.allowPaths</code></td><td>File paths exempt from file-access policy evaluation</td></tr><tr><td><code>metadata.commandLine.allowPaths</code></td><td>Executable paths exempt from command-line policy evaluation</td></tr><tr><td><code>metadata.privilegeElevation.allowPaths</code></td><td>Executable paths exempt from privilege-elevation policy evaluation</td></tr></tbody></table>

**Example — adding a path to the file-access allow-list:**

```json
{
  "id": "KeeperSystemExtension",
  "metadata": {
    "fileAccess": {
      "allowPaths": [
        "/System/Library/PrivateFrameworks",
        "/System/Library/CoreServices",
        "/System/Library/Frameworks",
        "/Library/Keeper",
        "/Applications/Keeper/KeeperNotify.app/Contents/MacOS/KeeperNotify",
        "/Applications/Keeper/KeeperTrash.app/Contents/MacOS/KeeperTrash",
        "/usr/libexec",
        "/usr/sbin",
        "/opt/yourcompany/internal-tool"
      ]
    }
  }
}
```

Only add paths you are confident do not need policy coverage. Adding too broadly may create gaps in policy enforcement.

### Updating Settings via Policy

System Extension settings can also be updated from the Admin Console using an **UpdateSettings** policy, without requiring manual file edits on each endpoint. When a settings update is applied, the extension fetches the revised configuration from `KeeperPrivilegeManager` over HTTPS. This is the recommended approach for fleet-wide configuration changes. See [Update Settings Policy Type](https://docs.keeper.io/en/keeperpam/endpoint-privilege-manager/policies/policy-types/advanced-policy-types/update-settings-policy-type) for details.

## Checking Extension Status

```bash
# List all loaded system extensions and their status
systemextensionsctl list

# Check System Extension approval status
spctl --status

# Verify the signing identity of the installed app
codesign -dv --verbose=4 "/Applications/Keeper/Keeper Endpoint Privilege Manager.app" 2>&1 | grep -E "Identifier|TeamIdentifier|Authority"

# Verify the signing identity of the System Extension specifically
codesign -dv --verbose=4 "/Applications/Keeper/Keeper Endpoint Privilege Manager.app/Contents/Library/SystemExtensions/com.keeper.keeper-privilege-manager.monitor.systemextension" 2>&1 | grep -E "Identifier|TeamIdentifier|Authority"
```

The Keeper extension should appear in `systemextensionsctl list` with status `[activated enabled]`. If it shows `[terminated waiting for user]`, the System Extension allowlist profile (see above) has not been deployed, or the user has not yet approved the extension in **System Settings → Privacy & Security**.

The `codesign` output should show:

* `Identifier=com.keeper.endpoint-privilege-manager` (for the app) or `Identifier=com.keeper.keeper-privilege-manager.monitor` (for the extension)
* `TeamIdentifier=234QNB7GCA`
* `Authority=Developer ID Application: Callpod Inc. (234QNB7GCA)` (Callpod is Keeper's parent company — see the note in the Identifiers table)

## Troubleshooting

**The extension is installed but privilege elevation is not being intercepted.** Confirm Full Disk Access has been granted to both the extension and the app. In System Settings → Privacy & Security → Full Disk Access, both `Keeper Endpoint Privilege Manager` and the `com.keeper.keeper-privilege-manager.monitor` extension should be listed and enabled. If the PPPC profile is deployed but FDA still shows as off, verify the `CodeRequirement` Team ID in your profile matches the actual signing Team ID returned by `codesign -dv`.

**Authorization petitions are timing out and users are blocked.** Either the KEPM service is not running, or the policy engine is not responding. Check that the service is running and that the KeeperPolicy plugin is in a Running state. If the service is healthy, check whether the timeout is set to a value that is too short for your approval workflow.

**Package installations are not being intercepted.** Verify the extension is in `[activated enabled]` state via `systemextensionsctl list`. If it is activated but packages are not being intercepted, confirm the KEPM service was running at the time of the installation attempt and review the service log for MQTT-level errors.

**The extension appears in `systemextensionsctl list` as `[terminated waiting for user]`.** The System Extension `allowlist` profile has not been received, or its `AllowedSystemExtensions` Team ID does not match the binary. Verify the profile is installed (`profiles show -type configuration`) and that the Team ID in the profile matches the output of `codesign -dv "/Applications/Keeper/Keeper Endpoint Privilege Manager.app/Contents/Library/SystemExtensions/com.keeper.keeper-privilege-manager.monitor.systemextension"`. On a user-managed Mac without MDM, re-open the Keeper Endpoint Privilege Manager app from `/Applications/Keeper/` and approve the extension manually in System Settings.

**The extension appears as `[terminated]` after a macOS upgrade.** Re-open the Keeper Endpoint Privilege Manager application from `/Applications/Keeper/` to trigger re-installation of the extension, then approve it in System Settings (or re-push the `allowlist` profile if MDM-managed).

**Users see "Notification not delivered" or no prompts for elevation requests.** The notifications PPPC profile has not been deployed, or the user has revoked notification permissions. The notification helper is a separate binary with its own bundle ID (`com.keeper.keepernotify`) — verify with `defaults read com.apple.ncprefs apps | grep com.keeper.keepernotify`. The entry should show a flags value indicating notifications are enabled. If the notification profile targets the wrong bundle ID (e.g. `com.keeper.endpoint-privilege-manager`), notifications will not be delivered.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://newdocs.keeper.io/en/keeperpam/endpoint-privilege-manager/deployment/deploy-with-macos/macos-system-extension-configuration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
