Ключ шифрования кук и сами куки уезжают в GlitchTip через текст исключения SQLAlchemy (все три сервиса сессий) #3194

Closed
opened 2026-08-28 18:50:38 +00:00 by bot-backend · 1 comment
Collaborator

Найдено ревью #3192. Дефект семейный — касается всех трёх сервисов сессий, не только нового.

Что происходит

cian_session.py, domclick_session.py и новый yandex_session.py передают ключ шифрования как bind-параметр:

db.execute(text("... pgp_sym_encrypt(:cookies_json, :key) ..."),
           {"cookies_json": ..., "key": settings.cookie_encryption_key})

Любое исключение из db.execute SQLAlchemy оборачивает в StatementError, и текст этого исключения содержит все bind-параметры:

[parameters: {... 'key': '<COOKIE_ENCRYPTION_KEY>', 'cookies_json': '...'}]

Дальше оно уезжает в GlitchTip как обычная ошибка.

Почему существующие защиты не помогают

  • main.py:121include_local_variables=False закрывает переменные фреймов, но не текст самого исключения.
  • traces_sample_rate=0.0 снимает вектор через span-data, но не через exception.
  • Обрезка по длине не спасает: SQLAlchemy режет только строки длиннее 300 символов, а ключ короткий — попадёт в отчёт целиком.

Достаточно одного таймаута соединения или дедлока на записи сессии, чтобы ключ оказался в трекере ошибок. Вместе с ним в том же тексте едет и cookies_json — то есть сами авторизационные куки.

Лечение

Однострочное и глобальное, в app/core/db.py:8:

create_engine(..., hide_parameters=True)

SQLAlchemy перестаёт печатать bind-параметры в тексте исключений.

Цена: в трейсбеках пропадут значения параметров, отладка SQL-ошибок станет чуть менее удобной. Для этого есть логи запросов на стороне БД; кладовку с ключами шифрования и живыми сессионными куками в трекер ошибок это не оправдывает.

Проверить заодно

Нет ли других мест, где секрет уезжает bind-параметром — grep по settings. внутри словарей параметров db.execute.

Приёмка

  • hide_parameters=True на движке
  • Тест: исключение из db.execute с секретным bind-параметром не содержит его значения в str(exc)
  • Проверено, что других секретов в bind-параметрах нет
  • Ротация COOKIE_ENCRYPTION_KEY — по решению владельца: если в GlitchTip уже есть такие отчёты, ключ следует считать раскрытым

Оценка S. Refs #3192

Найдено ревью #3192. **Дефект семейный** — касается всех трёх сервисов сессий, не только нового. ## Что происходит `cian_session.py`, `domclick_session.py` и новый `yandex_session.py` передают ключ шифрования как bind-параметр: ```python db.execute(text("... pgp_sym_encrypt(:cookies_json, :key) ..."), {"cookies_json": ..., "key": settings.cookie_encryption_key}) ``` Любое исключение из `db.execute` SQLAlchemy оборачивает в `StatementError`, и **текст этого исключения содержит все bind-параметры**: ``` [parameters: {... 'key': '<COOKIE_ENCRYPTION_KEY>', 'cookies_json': '...'}] ``` Дальше оно уезжает в GlitchTip как обычная ошибка. ## Почему существующие защиты не помогают - `main.py:121` — `include_local_variables=False` закрывает переменные **фреймов**, но не текст самого исключения. - `traces_sample_rate=0.0` снимает вектор через span-data, но не через exception. - Обрезка по длине не спасает: SQLAlchemy режет только строки длиннее 300 символов, а ключ короткий — попадёт в отчёт **целиком**. Достаточно одного таймаута соединения или дедлока на записи сессии, чтобы ключ оказался в трекере ошибок. Вместе с ним в том же тексте едет и `cookies_json` — то есть сами авторизационные куки. ## Лечение Однострочное и глобальное, в `app/core/db.py:8`: ```python create_engine(..., hide_parameters=True) ``` SQLAlchemy перестаёт печатать bind-параметры в тексте исключений. Цена: в трейсбеках пропадут значения параметров, отладка SQL-ошибок станет чуть менее удобной. Для этого есть логи запросов на стороне БД; кладовку с ключами шифрования и живыми сессионными куками в трекер ошибок это не оправдывает. ## Проверить заодно Нет ли других мест, где секрет уезжает bind-параметром — grep по `settings.` внутри словарей параметров `db.execute`. ## Приёмка - [ ] `hide_parameters=True` на движке - [ ] Тест: исключение из `db.execute` с секретным bind-параметром не содержит его значения в `str(exc)` - [ ] Проверено, что других секретов в bind-параметрах нет - [ ] Ротация `COOKIE_ENCRYPTION_KEY` — по решению владельца: если в GlitchTip уже есть такие отчёты, ключ следует считать раскрытым Оценка S. Refs #3192
bot-backend added the
bug
priority/p1
scope/backend
security
tradein
labels 2026-08-28 18:50:39 +00:00
Author
Collaborator

Закрываю: PR #3275 смержен (de31f279), на origin/main hide_parameters=True во всех 5 движках (backend/tradein × db.py/auth_db.py + alembic env), include_local_variables=False добавлен единственному непокрытому sentry_sdk.init (scheduler_main). Прод-проба 30.08: отказ на уровне запроса, имя таблицы в тексте есть, секрет — нет. Скан GlitchTip (31 417 событий, все партиции): утечки в окне с 31.05 нет; про более ранний период сказать нечем — ротация ключа остаётся решением владельца, зафиксировано в PR.

Закрываю: PR #3275 смержен (de31f279), на origin/main `hide_parameters=True` во всех 5 движках (backend/tradein × db.py/auth_db.py + alembic env), `include_local_variables=False` добавлен единственному непокрытому sentry_sdk.init (scheduler_main). Прод-проба 30.08: отказ на уровне запроса, имя таблицы в тексте есть, секрет — нет. Скан GlitchTip (31 417 событий, все партиции): утечки в окне с 31.05 нет; про более ранний период сказать нечем — ротация ключа остаётся решением владельца, зафиксировано в PR.
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#3194
No description provided.