---
title: "Package Rules - Workshop Docs"
description: "Package Rules - Enterprise control plane for Santa. Manage rules, approvals, telemetry, and policies across your macOS fleet."
doc_version: "1"
last_updated: "2026-08-20"
canonical: "https://northpole.security/docs/workshop/rules/package-rules"
---
# Package Rules

A package rule targets a piece of software by name in a package catalog (for example a Homebrew cask or an npm package) rather than by a raw hash or Team ID. Workshop resolves the package to its concrete identifiers and **materializes** ordinary execution rules from them. As new versions are published (or old ones stop matching your filters), Workshop re-resolves the package and adds or removes the materialized rules automatically, so you manage one package rule instead of a growing list of hashes.

One package rule can cover many versions and, depending on the rule type, many binaries per version. That reach is what makes the filters below useful: they let you narrow a broad package rule down to exactly the versions and binaries you want to trust.

## Creating a package rule

Open **Rules → Package Rules → New Package Rule**. A package rule has a few core fields plus the optional filters described later.

### Package source and name

Pick the **Package Source** that hosts the software, then enter the **Package Name** as it appears in that catalog:

Source

Name example

Homebrew

`wget` (formula)

Homebrew Cask

`firefox` (cask)

NPM

`express`

GitHub

`owner/repo`

Rust (crates.io)

`rustls`

VS Code

`publisher.name`

Terraform Plugin

`hashicorp/aws`

URL

a direct download URL

Nix

`ripgrep` (nixpkgs)

Workshop looks the package up in the catalog and reports how many execution rules it will create so you can see the reach before saving.

### Tags

Package rules respect the same tag scoping as other rules. Leave tags empty to apply the rule everywhere, or add one or more tags to limit it to the hosts that carry them.

### Policy

The **Policy** decides what the materialized execution rules do:

-   **Allow**: permit the package’s binaries to run.
-   **Allow as Compiler**: allow the binaries and treat them as trusted compilers for transitive allowlisting.
-   **Block**: prevent the package’s binaries from running.
-   **CEL**: evaluate a CEL expression at execution time to decide allow or block.

For **Block** and **CEL** policies you can set an optional **Custom Block Message** (shown to the user when execution is blocked, HTML supported) and a **Custom URL** for a help or appeal link.

### Preferred rule type

A package rule materializes into execution rules of the type you pick under **Preferred Rule Type**:

Rule type

Materializes to

Per-binary filter

Binary

one rule per binary

available

CDHash

one rule per binary

available

Signing ID

one rule per signing identity

not applicable

Team ID

one rule per signing identity

not applicable

Certificate

one rule per signing identity

not applicable

**Binary** and **CDHash** are the only types that expose per-binary identifiers, so the binary-selection filter is available only for them. The signing-identity types cover every binary signed with that identity, so there is nothing per-binary to filter.

## Simple filters

Every package rule can be narrowed with the built-in filters, all optional:

-   **Min Release Date** and **Max Release Date**: keep only versions released within a date window.
-   **Version Filter**: an RE2 regular expression matched against the version string (for example `^1\.` to pin to the 1.x series).

These are evaluated when Workshop resolves the package.

## Advanced CEL filters 2026.7

Two optional [CEL](https://northpole.security/docs/workshop/rules/cel-guide) expressions give you finer control than the simple filters. Open **Advanced (CEL Filters)** in the package rule dialog to set them.

Both filters:

-   Must evaluate to a **boolean**. `true` keeps the version or binary, `false` drops it.
-   Are **ANDed** with the simple filters above and with each other. A version or binary is covered only if every filter that applies to it returns `true`.
-   Are evaluated by **Workshop when it materializes the rule**, not by Santa at execution time. This is a different, smaller surface than the execution-context CEL described in the [CEL Guide](https://northpole.security/docs/workshop/rules/cel-guide): there is no execution context here, so no `target.*` signature fields, `args`, `ancestors`, or return-value keywords like `ALLOWLIST`, only the variables listed below and a boolean result. (The `target` variable in the version filter below is unrelated to execution CEL’s `target`: here it is a plain build-target string.)

### Version selection

The **Version Selection** filter runs for each build of each version. A version can ship several builds, one per platform target, and `target` lets you filter those individually. Use it to soak-test new releases, keep only the newest few versions, or drop builds for platforms you don’t ship.

Variables:

Variable

Type

Description

`version`

`string`

The version string, e.g. `1.25.0`

`released_at`

`timestamp`

Upstream release date of this version

`target`

`string`

Build target, e.g. `arm64_tahoe`

`latest_released_at`

`timestamp`

Release date of the newest version in the filtered set

`version_rank`

`int`

`1` for the newest version, increasing for older ones

`version_count`

`int`

Number of versions in the filtered set

`version_rank`, `version_count`, and `latest_released_at` are computed over the versions that already passed the simple filters (date window and version regexp), not the entire upstream catalog. Tightening a simple filter changes all three.

Helper functions (the same relative-time helpers used elsewhere in Workshop CEL):

```
now()      // the current time
today()    // the current date at UTC midnight
days(N)    // a duration of N days
```

Use `now() - days(30)` for relative windows. CEL’s `duration()` literal does not accept a day suffix (`duration("30d")` is invalid), so build day-scale durations with `days(N)`.

Examples:

```
// Soak new releases: only trust versions at least 30 days old.
released_at < now() - days(30)
```

```
// Keep only versions released within 60 days of the newest one.
released_at >= latest_released_at - days(60)
```

```
// Keep only the five newest versions.
version_rank <= 5
```

```
// Drop a build target you don't deploy.
!target.contains("bigsur")
```

```
// Only versions released in roughly the last year.
released_at > today() - days(365)
```

### Binary selection

The **Binary Selection** filter runs once per binary within a matched version. It is available only for the **Binary** and **CDHash** rule types, which create one rule per binary. Use it to allow a package’s main executable while excluding the bundled helper binaries it ships.

Variables:

Variable

Type

Description

`path`

`string`

Path of the binary inside the package, e.g. `Firefox.app/Contents/MacOS/firefox`

`hash`

`string`

SHA-256 hash of the binary

`cdhash`

`string`

Code directory hash of the binary

Paths are **package-relative**: they include the bundle root (for example `Firefox.app/Contents/MacOS/firefox`, or `wget/1.25.0/bin/wget` for a formula), not a path anchored at `Contents/`. Match with `contains` and `endsWith` rather than `startsWith` so a rule keeps working regardless of the bundle name:

```
// Exclude bundled helper binaries (auto-updaters, embedded frameworks, etc.).
!path.contains("/Contents/Frameworks/")
```

```
// Allow only the app's main executable.
path.endsWith("/Contents/MacOS/firefox")
```

Materialized rules are ordinary execution rules and are enforced by Santa like any other. See [Rule Packs](https://northpole.security/docs/workshop/rules/rule-packs) for the related mechanism that materializes a curated set of rules maintained by North Pole Security.

## Sitemap

- [Home](https://northpole.security/index.md)
- [Workshop](https://northpole.security/workshop.md)
- [Santa](https://northpole.security/santa.md)
- [Features](https://northpole.security/features.md)
- [Cookbook](https://northpole.security/cookbook.md)
- [Docs](https://northpole.security/docs.md)
- [Blog](https://northpole.security/blog.md)
- [Glossary](https://northpole.security/glossary.md)
- [About](https://northpole.security/about.md)
- [Contact](https://northpole.security/contact.md)
