# Santa Documentation > Documentation for Santa, a binary and file access authorization system for macOS from North Pole Security This file contains all documentation content in a single document following the llmstxt.org standard. ## Custom Branding Santa can display your organization's name or logo on every window it shows, so that users can tell who manages the machine and who to contact. Branding is configured with three keys, all documented on the [Configuration: Keys](/configuration/keys) page: `BrandingCompanyName`, `BrandingCompanyLogo`, and `BrandingCompanyLogoDark`. All three were added in Santa 2026.1. When any of them is set, Santa adds a "Managed by:" footer to the bottom of all notification dialogs (e.g. execution blocked, file access blocked, network flow blocked). ## Company name `BrandingCompanyName` is the simplest option: the name is shown as text. ```xml BrandingCompanyName Acme Corporation ``` ## Company logo `BrandingCompanyLogo` replaces the name with an image. The image is scaled down to fit within 84x28 points, so a wide wordmark works better than a tall or square logo. Supply the artwork at twice that size so that it stays sharp on a Retina display. Only the `file://` and `data:` URL schemes are supported. HTTP and HTTPS URLs are not, as Santa will not fetch a logo over the network: ```xml BrandingCompanyLogo file:///Library/Application%20Support/Acme/logo.png ``` If you use a `file://` URL, deploy the image alongside the profile and put it somewhere that is readable by all users. Otherwise, embed the image directly in the profile with a `data:` URL: ```xml BrandingCompanyLogo data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKgAAAA4CAYAAAC... ``` ### Dark mode Santa's windows follow the user's appearance setting, so a single-color logo that reads well on a light background can disappear on a dark one. `BrandingCompanyLogoDark` is used instead of `BrandingCompanyLogo` whenever the window is drawn in dark mode: ```xml BrandingCompanyLogo file:///Library/Application%20Support/Acme/logo.png BrandingCompanyLogoDark file:///Library/Application%20Support/Acme/logo-dark.png ``` The example below uses a dark wordmark for light windows and a light one for dark windows. **Light appearance** **Dark appearance** ## Precedence Only one piece of branding is ever displayed. The keys are evaluated in this order: | Order | Key | Used when | | ----- | ------------------------- | --------------------------------------------- | | 1 | `BrandingCompanyLogoDark` | The window is in dark mode and the key is set | | 2 | `BrandingCompanyLogo` | The key is set | | 3 | `BrandingCompanyName` | Neither logo key applies | A logo URL that uses any other scheme is ignored, as if the key was not set at all. If a logo URL is accepted but the image cannot be loaded - for example the file is missing, or is not an image format that macOS can read - Santa falls back to `BrandingCompanyName`. Set that key alongside the logo keys so that there is always something to display. ## Terminal messages Blocks that happen in a terminal are also branded, but only ever with `BrandingCompanyName`, as logos cannot be drawn on a TTY: ```text Santa The following application has been blocked from executing because its trustworthiness cannot be determined Reason: No matching rule Path: /Applications/Malware.app/Contents/MacOS/Malware Identifier: 60055b1f6fb276bfacf61f91505a72201987f20ad8b6867cce3058f4c0f0f5e5 Parent: bash (2511) Managed by: Acme Corporation ``` ## Custom messages Branding covers who manages the machine. To change what the dialogs _say_, see the `UnknownBlockMessage`, `BannedBlockMessage`, `FileAccessBlockMessage`, `BannedUSBBlockMessage`, `EventDetailURL`, and `EventDetailText` keys on the [Configuration: Keys](/configuration/keys) page. Rules synced from a server can also carry their own message and URL, which override the configured defaults. --- ## File-Access Authorization File Access Authorization (FAA) policies are defined using a plist configuration file. The policy can be specified either in a [separate file](/configuration/keys#FileAccessPolicyPlist) or [in-line](/configuration/keys#FileAccessPolicy) with the rest of the Santa configuration. If the policy is specified in a separate file, Santa will periodically re-read this file. By default this will occur every 10 minutes but the interval can be [overridden](/configuration/keys#FileAccessPolicyUpdateIntervalSec). ## Policy Structure The policy file has a hierarchical structure with root-level configuration and individual watch rules. ### Root Level Keys - `Version` (required): Policy version identifier that will be reported in events - `EventDetailURL` (optional): URL displayed when users receive block notifications. Supports [variable substitution](#eventdetailurl-placeholders) (e.g., `%hostname%`, `%rule_name%`, `%file_identifier%`) - `EventDetailText` (optional): Button label text for the notification dialog, maximum 48 characters. Defaults to 'Open'. - `WatchItems` (optional): Dictionary containing the individual monitoring rules :::tip If you want a default URL and button text for all file access events without configuring them in every FAA policy, you can set the global [FileAccessEventDetailURL](/configuration/keys#FileAccessEventDetailURL) and [FileAccessEventDetailText](/configuration/keys#FileAccessEventDetailText) configuration keys. Per-policy `EventDetailURL` and `EventDetailText` values (and per-rule overrides) will take precedence over these global defaults. ::: ### Watch Item Structure Each entry in the `WatchItems` dictionary represents a single rule. The key for each entry is the rule name, which will be used in logs and in the block notification UI. :::info Rule names (the `WatchItems` dictionary keys) must be 1-64 characters long and match the regular expression `^[A-Za-z0-9._:-]+$`, containing only letters, digits, periods, colons, hyphens, and underscores. For example, `ChromeCookies`, `my_rule_1`, and `my-rule.v2` are valid, but `My Rule` and `rule=1` are not. Invalid names will be rejected and an error will be logged. ::: Each rule contains three main components: - `Paths`: Array of path patterns to monitor - `Processes`: List of allowed/denied processes with specific identifiers - `Options`: Settings for rule behavior ## Basic Example ```xml Version v0.1 EventDetailURL https://my-server/faa/%hostname%/%rule_name%/%file_identifier% WatchItems UserFoo Paths Path /Users/*/tmp/foo IsPrefix Options AllowReadAccess AuditOnly RuleType PathsWithAllowedProcesses Processes TeamID EQHXZ8M8AV SigningID com.google.Chrome.helper ``` ## Path Configuration Paths can be specified using exact matches or wildcard patterns: - Exact paths: `/etc/sudoers` - Wildcards: `/Users/*/Documents/*` Each path entry can include: - `Path` (required): The path pattern to monitor - `IsPrefix` (optional): Boolean indicating whether the path represents prefix matching. When `true`, the rule will match files nested inside directories. When `false` or omitted, wildcards only match files/directories at that level without recursing. :::important If a configuration contains multiple rules with overlapping configured paths, only one rule will be applied. Which rule will be applied is undefined, so take care not to define rules with duplicate paths. ::: ### Path Globs Path globs represent a point-in-time snapshot. Globs are expanded when a configuration is applied and periodically re-evaluated based on the [FileAccessPolicyUpdateIntervalSec](/configuration/keys#FileAccessPolicyUpdateIntervalSec) setting. When multiple path globs or prefixes match an operation, the rule with the "most specific" or longest match is applied. Glob pattern support is provided by the libc [`glob(3)`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/glob.3.html) function. Extended glob patterns, such as globstar (`**`), are not supported. ### Path Resolution All configured paths are case-sensitive and must match the case as stored on the filesystem. Due to system limitations, Santa cannot reliably monitor hard-linked resources. To help mitigate bypasses, Santa will not allow the creation of hard links for monitored paths. If hard links previously existed for monitored paths, Santa cannot guarantee that access via these other links will be monitored. Configured path globs must refer to resolved paths only. Monitoring access on symbolic links is not supported. This is important as some common macOS paths are symbolic links (e.g., `/tmp` and `/var` are both symlinks into `/private`). ## Process Matching Processes can be matched using several identifiers: - **Signing ID**: Specified with the `SigningID` key (e.g., `EQHXZ8M8AV:com.google.Chrome.helper`) - **Team ID**: Specified with the `TeamID` key (e.g., `ZMCG7MLDV9`) - **Platform Binary**: Specified with the `PlatformBinary` boolean key - **CDHash**: Specified with the `CDHash` key (e.g., `397d55ebec87943ea3c3fe6b4d4f47edc490d25e`) - **Leaf Certificate Hash**: Specified with the `CertificateSha256` key - **Binary Path**: Specified with the `BinaryPath` key (e.g., `/Applications/Safari.app/Contents/MacOS/Safari`) :::tip Signing IDs must be scoped to a specific TeamID. You can use the same format as binary authorization rules where the SigningID is prefixed with the TeamID (e.g. `TeamID:SigningID`. For platform binaries, you can use the hard coded string `platform` as the TeamID (e.g. `platform:com.apple.yes`). ::: :::warning Specifying binaries by full path using `BinaryPath` is not very secure, as binaries can easily be moved. This should only be used as a last resort. Additionally, the `BinaryPath` key does not support glob patterns (`*`). ::: ## Rule Options The `Options` dictionary within each rule supports the following keys: - `RuleType` (required): Defines whether the rule is data-centric or process-centric: - `PathsWithAllowedProcesses`: Data-centric, only listed processes can access the paths - `PathsWithDeniedProcesses`: Data-centric, listed processes cannot access the paths - `ProcessesWithAllowedPaths`: Process-centric, listed processes can only access specified paths - `ProcessesWithDeniedPaths`: Process-centric, listed processes cannot access specified paths - `AllowReadAccess` (optional): Boolean controlling whether read access is allowed. When `false`, both read and write access are monitored/blocked. When `true`, only write access is monitored/blocked. Defaults to `true` if not specified. - `AuditOnly` (optional): Boolean. When `true`, violations are logged but not blocked. Defaults to `true`. - `EventDetailURL` (optional): Rule-specific URL that overrides the top-level EventDetailURL. - `EventDetailText` (optional): Custom button label text for this specific rule, overriding the root-level setting. - `BlockMessage` (optional): Custom message to be shown in the dialog presented to users upon a violation. Defaults to a reasonable, generic message that the action was blocked. - `EnableSilentMode` (optional): Boolean. When `true`, violations are logged but no notification is shown to the user. Defaults to `false`. - `EnableSilentTTYMode` (optional): Boolean. When `true`, violations are logged, but no notification is sent to the controlling TTY. Defaults to `false`. ## Rule Type Selection Choose your rule type based on what you're protecting: | Goal | Rule Type | | ----------------------------------------------------- | --------------------------------------------------------- | | Protect specific files/paths from unauthorized access | `PathsWithAllowedProcesses` or `PathsWithDeniedProcesses` | | Restrict what a specific process can access | `ProcessesWithAllowedPaths` or `ProcessesWithDeniedPaths` | **Data-centric example**: Protect browser cookies from theft by limiting access to the cookie files to only the browser processes. **Process-centric example**: Prevent AirDrop processes from reading files in folders containing sensitive corporate data. ## EventDetailURL placeholders When an FAA rule blocks access to a file, the user will be presented with a block notification dialog. On this dialog a button can be displayed which will take the user to a page with more information about that event. For the button to appear you must populate the `EventDetailURL` field, either at the top-level of the configuration or in an individual rule. This URL can contain placeholders, which will be populated at runtime; the supported placeholders are: | Placeholder | Description | | ------------------- | ------------------------------------------------------------------------------------------------------------------------- | | `%rule_version%` | Version of the rule that was violated | | `%rule_name%` | Name of the rule that was violated | | `%file_identifier%` | SHA-256 of the binary that was being executed | | `%accessed_path%` | The path that was being accessed | | `%username%` | The executing user | | `%team_id%` | The team ID that signed this binary, if any | | `%signing_id%` | The signing ID of this binary, if any | | `%cdhash%` | The binary's CDHash, if any | | `%machine_id%` | The ID of the machine, usually the hardware UUID unless [overridden](https://northpole.dev/configuration/keys/#MachineID) | | `%serial%` | The serial number of the machine | | `%uuid%` | The hardware UUID of the machine | | `%hostname%` | The system's full hostname | ## More Information For complete example policies and use-cases, see the [File-Access Authorization feature documentation](/features/faa) and the [FAA cookbook](/cookbook/faa). --- ## Config Generator :::warning This generator is still under active development and there are known rough edges with some of the more complex configuration keys as well as more features that will be coming soon. Please give it a try! ::: Use this form to generate a valid Santa configuration, ready to put inside a configuration profile and deploy to your machines. The generator will ensure that the configuration is valid and help storing default values. :::info The generation is all done inside your browser; the data you input never leaves your machine. ::: ## General --- ## Sync --- ## GUI --- ## FAA --- ## Rules --- ## Telemetry --- ## Removable Media (e.g. USB mass storage device) --- ## Metrics --- ## Generate Click the button to generate and download the generated configuration file. --- ## Keys This page describes all of the available configuration options recognized by Santa. The configuration keys are broken down into sections to make it easier to find what you're looking for but in the configuration profile all the keys should be set together. Some keys (or available values for a key) will have a badge showing which Santa version they were added or deprecated in. Where a key has been deprecated, the description will list an alternative if one is available. A key with next to the type can be overridden by a sync server. ## General General options ## Sync Options related to syncing ## GUI Options controlling how the GUI functions ## FAA Options controlling file-access authorization ## Rules Options controlling binary authorization rules ## Telemetry Options controlling the output of telemetry data ## Removable Media (e.g. USB device) Options controlling the Removable Media (e.g. USB device) mount control feature ## Metrics Options controlling the export of agent metrics --- ## CEL Playground Test and validate your [CEL expressions](/features/binary-authorization#cel) before deploying them. Enter a CEL expression and provide sample execution context as YAML, then evaluate to see the result and whether it would be cacheable. See the [CEL expressions cookbook](/cookbook/cel/) for example expressions. {() => { const CELPlayground = require('@site/src/components/CELPlayground').default; return ; }} :::info The evaluation is all done inside your browser; the data you input never leaves your machine. ::: --- ## Common Expression Language (CEL) This page lists well-known and/or community-contributed CEL expressions. CEL ([Common Expression Language](https://cel.dev/)) rules allow for more complex policies than would normally be possible. Read how to configure CEL rules in the [Binary Authorization](/features/binary-authorization#cel) documentation. ## Apps signed since X This will prevent executions of an app where the specific binary was signed before the provided date. This is particularly useful when attached to a `TEAMID` or `SIGNINGID` rule. ```clike target.signing_time >= timestamp('2025-05-31T00:00:00Z') ``` = timestamp('2025-05-31T00:00:00Z')`} context={` target: signing_time: "2025-06-01T00:00:00Z" args: - "--version" envs: HOME: "/Users/admin" euid: 501 cwd: "/Applications" `} /> ## Apps signed within the last N days This allows executions only when the binary was securely signed within a sliding window — here, the last 90 days — and blocks anything older. Unlike a fixed `timestamp(...)`, the window moves forward automatically each day, so the rule never needs to be re-pushed. `today()` is the start of the current UTC day and `days(n)` is `n`×24h (the standard `duration()` only parses units up to hours). This requires [Workshop](https://northpole.security/), and because `today()` changes daily the result is not cached. ```clike target.secure_signing_time > today() - days(90) ``` The example binary below was signed in 2020, so it falls outside the window and is blocked: today() - days(90)`} context={` target: secure_signing_time: "2020-01-01T00:00:00Z" args: - "--version" envs: HOME: "/Users/admin" euid: 501 cwd: "/Applications" `} /> ## Prevent users from disabling gatekeeper Create a signing ID rule for `platform:com.apple.spctl` and attach the following CEL program ```clike [ '--global-disable', '--master-disable', '--disable', '--add', '--remove' ].exists(flag, flag in args) ? BLOCKLIST : ALLOWLIST ``` ## Prevent Timestomping of LaunchAgents and LaunchDaemons Malware like those produced by the Chollima groups use "timestomping" to reset the timestamps of LaunchAgents and LaunchDaemons using touch. This can be prevented / detected by creating a SigningID rule for `platform:com.apple.touch` with the following CEL program. This technique was recently discussed by [Jaron Bradely](https://themittenmac.com/author/jaron-bradley/) at [Objective by the Sea v8](https://objectivebythesea.org/v8/talks.html#Speaker_24) ```clike args.exists(arg, arg in [ '-a', '-m', '-r', '-A', '-t' ]) && args.join(" ").contains("Library/Launch") ? BLOCKLIST : ALLOWLIST ``` Note this will not stop using the system calls directly or otherwise programmatically modifying the timestamps. Also this won't cover modifications if the process' current working directory is already in the LaunchDaemons / LaunchAgents directories. ## Prevent OSAScript From Popping Password Dialogs A lot of malware on macOS will attempt to get users to enter their passwords into a dialog box via osascript. This is a basic rule to stop directly asking for a password dialog. Make a SigningID rule for `platform:com.apple.osascript` with the following CEL Program ```clike ( args.join(" ").lowerAscii().matches(".*\\W+with\\W+hidden\\W+answer.*") || args.join(" ").lowerAscii().contains("password") ) && args.join(" ").lowerAscii().matches( ".*\\W+display\\W+dialog.*") ? BLOCKLIST : ALLOWLIST ```