YAML Conditions vs the Rego Policy DSL
Chainsaw has two policy surfaces — the built-in YAML / dashboard conditions and the signed Rego DSL. When to reach for each, and how they relate.
Overview
Chainsaw has two ways to express policy. They coexist, and most teams use both. This page is the short orientation: what each surface is, when to use which, and how they relate.
| YAML / dashboard conditions | Signed Rego DSL | |
|---|---|---|
| What | Built-in conditions chosen from a fixed set | Custom rules authored in Rego / OPA |
| Authored in | Dashboard, or YAML conditions: blocks | .rego files |
| Distributed via | YAML config / the API | A signed bundle (CHAINSAW_POLICY_BUNDLE) |
| Signed? | No | Yes — cosign-verified at load (enforced by default) |
| Best for | Single-signal gates (CVSS, license, malware, freshness) | Multi-field logic, surface-scoped rules, identity/coordinate patterns |
| Reference | YAML config guide | Policy DSL Reference |
The simpler surface: YAML / dashboard conditions
This is the surface most policies use. You pick a condition, an action, and a scope. In YAML it looks like this (see the full YAML config guide):
policies:
- name: Block Known Malware
action: block
enabled: true
precedence: 100
conditions:
malware_status: malicious
scope:
repositories: all
- name: Block Critical Vulnerabilities
action: block
conditions:
cvss_min: 9.0
- name: Block Copyleft Licenses
action: block
conditions:
license_match:
- AGPL-3.0-only
- GPL-3.0-only
The dashboard exposes the same conditions through the Policy Manager — see, for example, How to Block Vulnerable Packages Using CVSS and EPSS. These conditions are enforced natively by the Go evaluator; no Rego is involved.
The advanced surface: the signed Rego DSL
The DSL is for the long tail of rules that don’t map cleanly onto a single built-in condition. The same logic written above can be expressed in Rego, but the DSL earns its keep when a rule needs multiple fields, reacts to the enforcement surface, or keys on caller identity or coordinate patterns the YAML conditions don’t cover:
package chainsaw.policy
# Multi-field: only block when BOTH a young maintainer AND an
# install script are present — neither alone.
decision contains {
"action": "block",
"rule_id": "young-maintainer-with-install-script",
"message": "young maintainer + install script",
} if {
input.maintainerAccountAgeDays > 0
input.maintainerAccountAgeDays <= 90
input.hasInstallScript == true
}
DSL bundles are signed and verified at load — see Signed Policy Bundles.
When to use which
Reach for YAML / dashboard conditions when:
- The rule is a single signal with a threshold or match (CVSS, EPSS, license, trust score, freshness, malware, typosquat).
- You want non-engineers to manage it in the dashboard.
- You don’t want to run a signing pipeline.
Reach for the Rego DSL when:
- The rule combines several
input.*fields with custom logic. - You need to scope behavior by
input.surface(e.g. monitor at runtime, block at proxy). - You need to key on caller identity, client groups, IP/country, or package-coordinate patterns.
- You want the rule set itself to be a signed, attestable artifact.
How they relate
The two surfaces are evaluated together, and the stricter
action wins. A native YAML/dashboard block is never downgraded by a
DSL rule, and a DSL block is honored even when the native conditions
allow. A DSL monitor only escalates an otherwise-allow decision. If
your Rego throws an error, the DSL path fails open — the native
policy result still stands.
In practice: build your baseline of single-signal gates with YAML / dashboard conditions, then layer org-specific multi-field or surface-scoped rules on top with a signed DSL bundle.
Next Steps
- Policy DSL Reference — the full Rego authoring surface
- Signed Policy Bundles — author, sign, verify-at-load, promote
- How to Configure Chainsaw with YAML Configuration Files — the YAML
conditions:surface in full