учёт: закрыт переезд хранилища, заведён урожай его ревью
- storage-without-pocketbase закрыта как реализованная: приёмка сошлась по всем
пяти критериям записи и по двенадцати приёмочным свойствам рубрики ревью
дизайна, работа лежит коммитом c9b7765
- урожай триажа ревью развёрнут в одиннадцать записей с тегом партии
review-2026-08-23 и расставлен по зависимости, а не в конец списка
- находка про признак живости воркера слита в stalled-pipeline-metric: у неё та
же причина — вставший конвейер неотличим от простоя
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# 🐞 Судить маршрут по пути из запроса, а не по раскодированной копии
|
||||
|
||||
- **Тип:** fix
|
||||
- **Категория:** Очередь — Правится там же, где маршруты сводятся в одно место: суждение о пути и его объявление — один заход
|
||||
- **Зачем:** Адрес /%6detrics отдаёт метрики байт в байт: ServeMux сравнивает раскодированный путь, а правило прокси написано на литерал /metrics — тот же класс, что закрытый /%5f/.
|
||||
- **Теги:** review-2026-08-23
|
||||
|
||||
Правило обратного прокси написано на литерал `/metrics`, а `net/http` сравнивает
|
||||
путь **после** раскодирования процентных последовательностей. Адрес
|
||||
`/%6detrics` правилу прокси не совпадает, а `ServeMux` отдаёт по нему тот же
|
||||
обработчик метрик.
|
||||
|
||||
Тот же класс закрыт задачей `storage-without-pocketbase` для `/%5f/` — там путь
|
||||
исчез вместе с пространством хранилища. Здесь путь остаётся, и обойти можно
|
||||
всякое правило прокси, написанное на литерал.
|
||||
|
||||
Серьёзность понижена тем, что метрики объявлены открытыми без узнавания —
|
||||
[security.md](../../docs/security.md), — то есть сегодня обход не даёт того, чего
|
||||
нельзя получить прямым запросом. Дефект в том, что суждение о пути расходится
|
||||
между сервисом и прокси: следующий закрытый прокси адрес обойдётся так же.
|
||||
|
||||
Нашёл проход `review-adversary` (V3) ревью change
|
||||
`2026-08-23-storage-without-pocketbase`, проверено сырыми запросами.
|
||||
|
||||
## Воспроизведение
|
||||
|
||||
1. Поднять сервис локально.
|
||||
2. `curl -s http://<адрес>/%6detrics` — приходит страница метрик байт в байт,
|
||||
как по `/metrics`.
|
||||
3. Правило прокси, написанное на литерал `/metrics`, такой путь не узнаёт и
|
||||
пропускает его наружу.
|
||||
|
||||
## Затрагивает
|
||||
|
||||
- перечень корней сервиса `internal/controller/http/mounts.go` — сравнение пути
|
||||
в `Mount.Covers` и `ExactAddressOf`;
|
||||
- подъём сервера и раздача слушателей в `cmd/transcriber`;
|
||||
- публичный контракт HTTP: адреса `/metrics` и `/health`;
|
||||
- модель угроз `docs/security.md` — строка об открытых метриках и о том, чем
|
||||
держится закрытость адреса.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- Перекодированный адрес метрик не отдаёт метрики. **Оракул:** тест маршрутов —
|
||||
`/%6detrics`, `/%6D%65trics` и `/metrics/` отвечают эталоном неизвестного
|
||||
пути, а `/metrics` отвечает метриками.
|
||||
- Тем же эталоном отвечает перекодированный адрес всякого точного корня.
|
||||
**Оракул:** тот же тест на `/%68ealth`.
|
||||
- В журнал перекодированный путь идёт своим полем длины, а не дословно.
|
||||
**Оракул:** тест журнала — строка о таком запросе несёт `<приложение>` либо
|
||||
точный адрес, а не текст спрашивающего.
|
||||
|
||||
## Рамки
|
||||
|
||||
Правило обратного прокси живёт в чужом репозитории `pet-project-server`, и эта
|
||||
задача его не правит: сервис обязан судить о своём адресном пространстве сам.
|
||||
Открытость метрик без узнавания решением не пересматривается — вопрос в том, по
|
||||
какому пути они отдаются.
|
||||
Reference in New Issue
Block a user