# 🐞 Судить маршрут по пути из запроса, а не по раскодированной копии - **Тип:** 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`, и эта задача его не правит: сервис обязан судить о своём адресном пространстве сам. Открытость метрик без узнавания решением не пересматривается — вопрос в том, по какому пути они отдаются.