YAML Conditions vs the Rego Policy DSL

Intermediate 10 minutes Security Engineers / Platform Engineers Security & Policy Advanced Configuration

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 conditionsSigned Rego DSL
WhatBuilt-in conditions chosen from a fixed setCustom rules authored in Rego / OPA
Authored inDashboard, or YAML conditions: blocks.rego files
Distributed viaYAML config / the APIA signed bundle (CHAINSAW_POLICY_BUNDLE)
Signed?NoYes — cosign-verified at load (enforced by default)
Best forSingle-signal gates (CVSS, license, malware, freshness)Multi-field logic, surface-scoped rules, identity/coordinate patterns
ReferenceYAML config guidePolicy 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