From dd556e2f05c16951a5d6aa0c90955ec6152e88cb Mon Sep 17 00:00:00 2001 From: Gros Frumos Date: Sat, 21 Mar 2026 10:55:34 +0200 Subject: [PATCH] sec: pre-commit hook + httpx exception logging hardening MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .pre-commit-config.yaml | 11 +++++++++++ backend/telegram.py | 9 ++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..7732a47 --- /dev/null +++ b/.pre-commit-config.yaml @@ -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$' diff --git a/backend/telegram.py b/backend/telegram.py index e8af507..4b37a7e 100644 --- a/backend/telegram.py +++ b/backend/telegram.py @@ -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: