Policy Reference

YAML policy files configure how tirith responds to detected threats.

Policy Discovery

Tirith discovers policy files by walking up the directory tree from the current working directory to the nearest .git boundary, looking for:

  • -.tirith/policy.yaml (then .yml)
  • -Fallback: ~/.config/tirith/policy.yaml

Example Policy

policy.yaml
# .tirith/policy.yaml
fail_mode: closed
 
allowlist:
- "*.example.com"
- "registry.npmjs.org"
- "ghcr.io/*"
 
blocklist:
- "evil.example"
- "*.malware.test"
 
severity_overrides:
plain_http_to_sink: HIGH
shortened_url: LOW
 
allow_bypass_env: false

Fields

fail_mode

Controls behavior when the engine encounters an error. open allows execution to proceed, closed blocks execution on error. Default: open.

allowlist

A list of glob patterns for domains and URLs that should be excluded from findings. Matching URLs will not trigger any rules. Supports wildcards.

blocklist

A list of glob patterns for domains that should always be blocked, regardless of rule results. Blocklist overrides allowlist when both match.

severity_overrides

Override the default severity for specific rule IDs. Valid values: CRITICAL, HIGH, MEDIUM, LOW. This lets you escalate or de-escalate specific rules per your organization's risk tolerance.

allow_bypass_env

When true, users can set TIRITH_BYPASS=1 to skip blocking. Default: false. Useful for CI environments where a human has reviewed the command.

Custom Rules & the when: DSL

Beyond allowlists and severity overrides, you can author your own detection rules under custom_rules. A rule is either a regex match or a semantic when: clause, never both. The DSL evaluates against data the engine already extracted (URLs, packages, command shape, files), so it adds no new parsing and no hot-path network. Reputation predicates read the local threat database.

.tirith/policy.yaml
custom_rules:
- id: block-unknown-curl-to-shell
when:
all:
- command.has_pipeline_to: [sh, bash, zsh]
- url.reputation: unknown
- url.domain_not_in: [company.com, github.com]
action: block
severity: critical
message: "Unknown-domain script piped to shell"
context: [exec]

Combine predicates with all, any, and not. Predicate families:

  • -command.*uses_sudo, has_pipeline_to, cwd_in
  • -url.*scheme, host, host_matches, reputation, domain_not_in
  • -package.*ecosystem, name_matches, reputation
  • -file.*path_matches

Author and check rules with tirith rule test|validate|explain. validate rejects a DSL rule whose predicates don't apply to its declared context, so a rule can never be silently dead.

Centralized Policies (Team+)

Team and Enterprise tiers can manage policies centrally through the admin console. The CLI fetches the active policy from the server on startup and caches it locally. Local policy files are merged with the server policy, with the server taking precedence.