alert-ack пишет секрет вебхука GlitchTip в access-log открытым текстом — фикс #3154 закрыл только бэкенд МЕРЫ #3576

Open
opened 2026-09-17 09:47:51 +00:00 by bot-backend · 1 comment
Collaborator

Найдено 17.09.2026 при проверке доставки тревоги GlitchTip (#2214).

Факт

docker logs gendesign-alert-ack на Beget печатает строку доступа целиком, включая query-параметр с секретом:

2026-09-17 09:35:38,394 INFO 172.19.0.6 "POST /glitchtip?secret=<значение> HTTP/1.1" 200 -

Логи контейнеров Beget собирает Alloy и отправляет в Loki, так что секрет лежит и там.

Почему это тот же класс, что #3154

#3154 закрыл утечку секрета из access-log uvicorn в tradein-backend — там теперь secret=***. Но у GlitchTip два получателя вебхука (ProjectAlert id=3 проекта Trade-In): бэкенд МЕРЫ и https://metrics.gendsgn.ru/glitchtip → alert-ack. Второй путь фикс не покрыл. Правильный образец лежит рядом: маскирование в бэкенде МЕРЫ.

Что сделать

  1. В alert-ack (ops/metrics/alert-ack/app.py, werkzeug/стандартный логгер доступа) маскировать secret в строке запроса так же, как в бэкенде МЕРЫ. Тест: запрос с секретом → в записи лога значения нет.
  2. Ротировать секрет — он уже в Loki и в этой задаче не приводится. Менять одновременно в env alert-ack и в URL получателя GlitchTip (AlertRecipient id=6). Это действие владельца/по его решению.
  3. Проверить, не остался ли секрет в Loki за период хранения, и решить, чистить ли.

Приёмка

После деплоя alert-ack тестовый вебхук оставляет в docker logs gendesign-alert-ack строку без значения секрета; старый секрет больше не принимается (401), новый — принимается.

Refs #3154, #2214.

Найдено 17.09.2026 при проверке доставки тревоги GlitchTip (#2214). ## Факт `docker logs gendesign-alert-ack` на Beget печатает строку доступа целиком, включая query-параметр с секретом: ``` 2026-09-17 09:35:38,394 INFO 172.19.0.6 "POST /glitchtip?secret=<значение> HTTP/1.1" 200 - ``` Логи контейнеров Beget собирает Alloy и отправляет в Loki, так что секрет лежит и там. ## Почему это тот же класс, что #3154 #3154 закрыл утечку секрета из access-log **uvicorn в tradein-backend** — там теперь `secret=***`. Но у GlitchTip два получателя вебхука (ProjectAlert id=3 проекта Trade-In): бэкенд МЕРЫ и `https://metrics.gendsgn.ru/glitchtip` → alert-ack. Второй путь фикс не покрыл. Правильный образец лежит рядом: маскирование в бэкенде МЕРЫ. ## Что сделать 1. В alert-ack (`ops/metrics/alert-ack/app.py`, werkzeug/стандартный логгер доступа) маскировать `secret` в строке запроса так же, как в бэкенде МЕРЫ. Тест: запрос с секретом → в записи лога значения нет. 2. **Ротировать секрет** — он уже в Loki и в этой задаче не приводится. Менять одновременно в env alert-ack и в URL получателя GlitchTip (`AlertRecipient` id=6). Это действие владельца/по его решению. 3. Проверить, не остался ли секрет в Loki за период хранения, и решить, чистить ли. ## Приёмка После деплоя alert-ack тестовый вебхук оставляет в `docker logs gendesign-alert-ack` строку без значения секрета; старый секрет больше не принимается (401), новый — принимается. Refs #3154, #2214.
Author
Collaborator

Поправка к формулировке задачи: секрета в Loki нет — 17.09.2026

В описании сказано, что секрет «лежит и в Loki». Это неверно, проверено запросами в gendesign-loki за 29 суток (только чтение):

  • строк alert-ack с secret= — 106 (12.09–17.09), во всех secret=***, значения нет;
  • по всему инфраструктурному хосту (включая Caddy) строк с незамаскированным secret= — 0.

Alloy маскирует значение до отправки (#3354). Открытым текстом значение есть только на самом Beget — в docker logs gendesign-alert-ack и journald. Поэтому:

  • пункт 3 («проверить Loki и решить, чистить ли») снимается — чистить нечего;
  • ротация остаётся за владельцем, но срочность ниже: круг лиц, видевших значение, — те, у кого есть доступ к Beget.

Маскирование в самом alert-ack — PR #3588: Handler.log_message маскирует значение и в строке доступа, и в тексте ошибки разбора запроса, тем же выражением, что у бэкенда МЕРЫ (#3154) и Alloy (#3354). Тест на настоящем сокете + фальсификация.

Смежная находка (не в этой задаче): одноразовый токен кнопки /ack/<token> передаётся в пути, а не в query, поэтому пишется в лог как есть и Alloy его тоже не маскирует — он в Loki. Кто имеет доступ к Grafana, может принять инцидент за дежурного. Стоит решить: маскировать путь /ack/… в логе или признать приемлемым (токен одноразовый).

## Поправка к формулировке задачи: секрета в Loki нет — 17.09.2026 В описании сказано, что секрет «лежит и в Loki». **Это неверно**, проверено запросами в `gendesign-loki` за 29 суток (только чтение): - строк alert-ack с `secret=` — 106 (12.09–17.09), **во всех `secret=***`**, значения нет; - по всему инфраструктурному хосту (включая Caddy) строк с незамаскированным `secret=` — 0. Alloy маскирует значение до отправки (#3354). Открытым текстом значение есть только на самом Beget — в `docker logs gendesign-alert-ack` и journald. Поэтому: - пункт 3 («проверить Loki и решить, чистить ли») снимается — чистить нечего; - **ротация остаётся за владельцем**, но срочность ниже: круг лиц, видевших значение, — те, у кого есть доступ к Beget. **Маскирование в самом alert-ack** — PR #3588: `Handler.log_message` маскирует значение и в строке доступа, и в тексте ошибки разбора запроса, тем же выражением, что у бэкенда МЕРЫ (#3154) и Alloy (#3354). Тест на настоящем сокете + фальсификация. **Смежная находка (не в этой задаче):** одноразовый токен кнопки `/ack/<token>` передаётся в **пути**, а не в query, поэтому пишется в лог как есть и Alloy его тоже не маскирует — он в Loki. Кто имеет доступ к Grafana, может принять инцидент за дежурного. Стоит решить: маскировать путь `/ack/…` в логе или признать приемлемым (токен одноразовый).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3576
No description provided.