Configuration

Policy file reference, cookbook recipes, bypass mechanism, and data handling.

01Policy Discovery#

Tirith uses a YAML policy file. Discovery order:

  1. TIRITH_POLICY_ROOT env var → $TIRITH_POLICY_ROOT/.tirith/policy.yaml
  2. Walk up from CWD looking for .tirith/policy.yaml (or .yml)
  3. ~/.config/tirith/policy.yaml (user-level fallback)

02Policy Fields#

FieldTypeDescription
versionnumberPolicy format version (currently 1)
fail_mode"open" | "closed"open allows execution on engine error; closed blocks. Default: open
allowliststring[]Glob patterns for domains/URLs excluded from findings
blockliststring[]Glob patterns for domains that are always blocked. Overrides allowlist.
severity_overridesmap<rule_id, severity>Override default severity for specific rule IDs (CRITICAL, HIGH, MEDIUM, LOW)
allow_bypass_envbooleanAllow TIRITH=0 bypass. Default: true. Set false for strict environments.

03Cookbook Recipes#

Strict Organization (Fail Closed, No Bypass)

All findings block execution. No bypass mechanism. Shortened URLs and plain HTTP escalated.

.tirith/policy.yaml
# .tirith/policy.yaml (repo root)
fail_mode: closed
allow_bypass_env: false
severity_overrides:
shortened_url: HIGH
plain_http_to_sink: CRITICAL

Personal Developer (Defaults + Allowlist)

Default severity mappings. Allowlisted URLs skip analysis.

~/.config/tirith/policy.yaml
# ~/.config/tirith/policy.yaml
fail_mode: open
allow_bypass_env: true
allowlist:
- "raw.githubusercontent.com"
- "homebrew.bintray.com"
- "get.docker.com"

Docker-Focused (Escalate Docker Rules)

All Docker-related findings escalated. Other rules use default severity.

policy.yaml
severity_overrides:
docker_untrusted_registry: CRITICAL
docker_tag_latest: HIGH

Learning Mode (All Low Severity)

Everything becomes a LOW-severity warning. Nothing blocks. Useful for onboarding.

policy.yaml
fail_mode: open
allow_bypass_env: true
severity_overrides:
curl_pipe_shell: LOW
wget_pipe_shell: LOW
pipe_to_interpreter: LOW
punycode_domain: LOW
confusable_domain: LOW

Cargo Vet Supply-Chain Audit

Escalate the vet_not_configured rule for Rust projects using cargo-vet.

policy.yaml
severity_overrides:
vet_not_configured: HIGH

To suppress instead (e.g. for non-Rust repos), add vet_not_configured to your allowlist.

04Bypass#

For the rare case you know exactly what you're doing:

shell
$ TIRITH=0 curl -L https://something.xyz | bash

This is a standard shell per-command prefix — the variable only exists for that single command. Bypasses are logged to the audit trail with bypass_requested: true.

Note: Organizations can disable bypass entirely with allow_bypass_env: false in policy.

05Data Handling#

Local JSONL audit log at ~/.local/share/tirith/log.jsonl:

  • +Timestamp, action, rule ID, redacted command preview
  • -No full commands, environment variables, or file contents

Disable: export TIRITH_LOG=0

06Design Principles#

Offline by defaultcheck, paste, score, diff, and why make zero network calls. All detection runs locally.
No command rewritingtirith never modifies what you typed.
No telemetryNo analytics, no crash reporting, no phone-home behavior.
No background processesInvoked per-command, exits immediately.
Network only when you askrun, fetch, license refresh, and audit report --upload reach the network, but only on explicit invocation.