sec: pre-commit hook + httpx exception logging hardening

1. .pre-commit-config.yaml — local pygrep hook блокирует коммиты
   с токенами формата \d{9,10}:AA[A-Za-z0-9_-]{35} (Telegram bot tokens).
   Проверено: срабатывает на токен, пропускает чистые файлы.

2. backend/telegram.py — три функции (send_registration_notification,
   answer_callback_query, edit_message_text) логировали exc напрямую,
   что раскрывало BOT_TOKEN в URL httpx-исключений в journalctl.
   Заменено на type(exc).__name__ — только тип ошибки, без URL.

Refs: #1303, #1309, #1283

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gros Frumos 2026-03-21 10:55:34 +02:00
parent 5401363ea9
commit dd556e2f05
2 changed files with 17 additions and 3 deletions

11
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,11 @@
repos:
- repo: local
hooks:
- id: no-telegram-bot-token
name: Block Telegram bot tokens
# Matches tokens of format: 1234567890:AAFisjLS-yO_AmwqMjpBQgfV9qlHnexZlMs
# Pattern: 9-10 digits, colon, "AA", then 35 alphanumeric/dash/underscore chars
entry: '\d{9,10}:AA[A-Za-z0-9_-]{35}'
language: pygrep
types: [text]
exclude: '^\.pre-commit-config\.yaml$'

View file

@ -106,7 +106,8 @@ async def send_registration_notification(
resp.text,
)
except Exception as exc:
logger.error("send_registration_notification error: %s", exc)
# Do not log exc directly — httpx exceptions embed the full API URL with BOT_TOKEN
logger.error("send_registration_notification error: %s", type(exc).__name__)
async def answer_callback_query(callback_query_id: str) -> None:
@ -118,7 +119,8 @@ async def answer_callback_query(callback_query_id: str) -> None:
if resp.status_code != 200:
logger.error("answerCallbackQuery failed %s: %s", resp.status_code, resp.text)
except Exception as exc:
logger.error("answerCallbackQuery error: %s", exc)
# Do not log exc directly — httpx exceptions embed the full API URL with BOT_TOKEN
logger.error("answerCallbackQuery error: %s", type(exc).__name__)
async def edit_message_text(chat_id: str | int, message_id: int, text: str) -> None:
@ -132,7 +134,8 @@ async def edit_message_text(chat_id: str | int, message_id: int, text: str) -> N
if resp.status_code != 200:
logger.error("editMessageText failed %s: %s", resp.status_code, resp.text)
except Exception as exc:
logger.error("editMessageText error: %s", exc)
# Do not log exc directly — httpx exceptions embed the full API URL with BOT_TOKEN
logger.error("editMessageText error: %s", type(exc).__name__)
async def set_webhook(url: str, secret: str) -> None: