Skip to main content

tirith-config

Operate tirith, the terminal guard against homograph URLs, ANSI injection, and pipe-to-shell. Use when editing ~/.config/tirith/policy.yaml, debugging a blocked command or paste, choosing trust / allowlist / download-and-run / TIRITH=0, or quieting a noisy rule.

ソース情報

リポジトリ
nweii/agent-stuff
ソースの最終更新活動
2026年10月2日 15:59
検出された SKILL.md の言語
英語
スター
10
フォーク
0

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
tirith-config
description
Operate tirith, the terminal guard against homograph URLs, ANSI injection, and pipe-to-shell. Use when editing ~/.config/tirith/policy.yaml, debugging a blocked command or paste, choosing trust / allowlist / download-and-run / TIRITH=0, or quieting a noisy rule.
metadata
{"author":"nweii","version":"1.2.0"}
# tirith-config Tirith intercepts shell commands and pasted content to catch homograph URLs (Cyrillic lookalikes, mixed scripts), ANSI escape injection, and `curl | bash`–style pipe-to-shell patterns. This skill encodes operating procedure — decision logic, verification rituals, and inherent gotchas. The current allowlist and tool version are not encoded here; query them at runtime. ## Operating model Tirith has four moving parts. Treat the live config as source of truth, not memory: - **Shell hook** — sourced via `eval "$(tirith init --shell zsh)"` in the user's shell profile. This is what wires per-command interception. Hook source files at `~/.local/share/tirith/shell/` are inert until the eval line is added to the profile. - **Policy file** — `~/.config/tirith/policy.yaml` (global) and `.tirith/policy.yaml` (per-project, walks up from cwd). The per-project file wins when present. - **Audit log** — `~/.local/share/tirith/log.jsonl`. Redacted previews, not full commands. - **Receipts** — created by `tirith run <url>`. Verifiable later with `tirith receipt verify <sha256>`. `tirith doctor` is the canonical health check; it surfaces hook status, policy detection, and bypass mode in one shot. ## Decision tree: a command was blocked Four responses, each appropriate for a different shape of problem: Run `tirith why` first. The rule ID decides which response fits: a pipe-to-shell rule (`curl_pipe_shell`) and a hostname rule (`lookalike_tld`, which flags `.dev`, `.app`, `.zip` and similar TLDs) both clear through trust, but only the first is about the script itself. 1. **Trust the source** — for a vendor you trust. `tirith trust last` shows the last trigger and offers to trust its domain interactively; `tirith trust from-last-trigger` prints the narrowest matching `tirith trust add` command (`--apply` runs it). Entries are scoped to one rule when `--rule` is given, expire after 30 days unless `--permanent` or `--ttl` says otherwise, and are recorded in the trust audit (`tirith trust list`, `tirith trust audit`). Prefer this over the policy allowlist for anything short of a canonical installer. 2. **Allowlist the hostname** — only for canonical installer domains you pipe-shell from repeatedly (e.g., `get.docker.com`, `sh.rustup.rs`). Add to `allowlist:` in `~/.config/tirith/policy.yaml`. An entry suppresses every hostname-scoped rule for that exact host, `lookalike_tld` included; content-level checks (homograph, mixed-script, ANSI) still run. It never expires, which is why trust (1) is the better default. 3. **Download, read, run** — `curl -fsSL <url> -o /tmp/install.sh`, read the file, then `sh /tmp/install.sh`. A plain download is not pipe-to-shell and only trips hostname rules, which warn. This is the most reliable one-off path, and the only one that takes interpreter arguments (`curl … | bash -s -- --prefix /opt`). 4. **`tirith run <url>`** — downloads to a temp file, shows SHA256, runs static analysis, and writes a receipt. It fetches the URL itself, so the original `curl` flags have no counterpart. **Execution is Linux-only**: on macOS it inspects and stops, so follow it with (3) to actually install. `tirith run <url> | sh` pipes the analysis report, not the script, into the shell. 5. **`TIRITH=0` prefix** — honored when the command is checked at Enter, not by the paste scanner. The paste scanner analyzes the pasted text and does not read an assignment inside it, so pasting `TIRITH=0 curl … | sh` is still blocked at paste time, and typing `TIRITH=0 ` before pasting does not help because only the pasted chunk is scanned. It works for a command typed in full. `export TIRITH=0` disables both checks for the whole shell until `unset TIRITH`, which is broader than the problem. Policy's `allow_bypass_env` governs both. Confirm against the installed build: `tirith check --interactive --shell posix -- 'TIRITH=0 curl -fsSL https://example.com/x.sh | sh'` exits 0, while the same text piped to `tirith paste --shell posix --interactive` exits 1. If none of these fit, the command probably shouldn't run. ## Adding to the allowlist ```yaml allowlist: - "vendor.example.com" # one entry per line, exact hostname ``` Hostnames only — no globs, no path-aware matching. After editing: ```bash tirith doctor # confirm policies: still resolves tirith check -- curl -fsSL https://vendor.example.com \| bash # should exit 0 tirith check -- curl -fsSL https://vendor-not-listed.com \| bash # should still exit 1 with curl_pipe_shell ``` Both checks together confirm the allowlist took effect *and* didn't accidentally widen the policy. ## Quieting a noisy rule When a rule fires mostly on legitimate traffic, lower its severity instead of disabling tirith or allowlisting around it: ```yaml severity_overrides: lookalike_tld: LOW ``` At paranoia 1–2, only Medium+ findings surface, so LOW keeps the rule in the audit log without interrupting. `tirith warnings` and `tirith doctor`'s detection-coverage block still count it. `tirith explain --rule <id>` documents any rule (`--list` enumerates them), and `tirith policy tune --from-audit` suggests changes from the log. ## Anti-patterns for the allowlist - **Don't allowlist broad CDNs.** `raw.githubusercontent.com`, `gist.githubusercontent.com`, `cdn.jsdelivr.net`, `s3.amazonaws.com`, `*.vercel.app` — anyone can host arbitrary scripts on these. Allowlisting them gives a security tool a wide blind spot. Use download-read-run, or a URL-scoped `tirith trust add <host>/<path>`, for one-off scripts hosted on shared infrastructure. - **Don't allowlist subdomains preemptively.** Add what you actually use, not what you might use someday. - **Don't allowlist as a way to silence noise.** If tirith blocks something repeatedly that you don't actually trust, the right move is to stop running that command, not to suppress the warning. ## Verification ritual after any config change Run all four: ```bash tirith policy validate # 0 errors, 0 warnings tirith doctor # hook status: configured / policies: <path> tirith policy test '<a known-blocked cmd>' # action: Block — rules still fire tirith policy test '<an allowlisted cmd>' # action: Allow — the change took effect ``` `tirith doctor` alone is not sufficient — it reports config detection, not rule behavior. `tirith policy validate` is the only check that catches misspelled fields: tirith ignores unknown keys with a warning, so `allow_bypass:` (the real key is `allow_bypass_env`) or `version:` (the real key is `schema_version`) silently do nothing. `tirith policy effective` prints the fully resolved policy with defaults filled in. To test a candidate policy without touching the live file, point `TIRITH_POLICY_ROOT` at a directory holding `.tirith/policy.yaml` and run `tirith policy test` with it set. ## After a brew upgrade `brew upgrade tirith` may re-materialize hook source files. The shell profile line stays put, so usually nothing breaks, but verify: ```bash tirith --version tirith doctor ``` If `hook status` ever drops back to `NOT CONFIGURED` after an upgrade, re-run `eval "$(tirith init --shell zsh)"` and confirm the profile line is still present. Do not blindly append a duplicate. ## Reading the audit log ```bash tail -20 ~/.local/share/tirith/log.jsonl | jq . # last 20 events tirith why # explains last triggered rule tirith receipt last # last `tirith run` receipt tirith receipt list # all receipts ``` The log only stores redacted command previews — not full commands, env vars, or file contents. Disable logging entirely with `export TIRITH_LOG=0`. ## Per-project policies For client work that needs stricter rules than the global config, drop a `.tirith/policy.yaml` at the project root. Tirith walks up from the current directory and uses the first match. A repo-scoped policy is **tightening-only**: weakening fields such as `allowlist` are ignored with a notice, so a cloned repo cannot loosen your protection. Loosen at user scope (global policy or `tirith trust add --scope user`). `tirith policy effective` shows which fields were neutralized. ## Inherent gotchas - **Profile edits affect new shells only.** After modifying the shell profile, open a fresh terminal tab or `source ~/.zshrc`. The current shell will not pick up the change. - **`tirith check -- <cmd>`** — the `--` is required. Without it, flags on `<cmd>` (e.g., `-sSL`) get parsed as tirith's own flags. - **Shell quoting matters in `tirith check`.** Pipe characters and parens need escaping (`\|`, `\(`) since the command is parsed by your shell first. - **`fail_mode: open`** allows commands through when tirith itself errors internally. Use `fail_mode: closed` only in environments where blocking on parser errors is acceptable. - **License key absence is normal.** OSS rules work without one; only paid features (e.g., team audit) require activation. ## What this skill deliberately does not encode - **The current allowlist contents** — read `~/.config/tirith/policy.yaml` directly. - **The current tirith version** — `tirith --version`. - **Whether the hook is currently configured** — `tirith doctor`. - **Specific zshrc line text** — `tirith init --shell zsh` always prints the current correct line; pipe its output rather than copy-pasting from anywhere. The skill is a stable operating manual. Live state is queried at runtime.
GitHubで見る