"""#3194: bind-параметры не должны попадать в текст исключения (→ GlitchTip). Через них уезжали ключ шифрования кук и сами куки: сервисы сессий зовут `db.execute(text("... pgp_sym_encrypt(:cookies_json, :key) ..."), {...})`, а SQLAlchemy при ошибке оборачивает всё в StatementError и печатает ВСЕ параметры в `str(exc)`. Отказ здесь обязан произойти НА УРОВНЕ ЗАПРОСА: если соединение падает на CONNECT, до bind-параметров дело не доходит и тест зелёный по построению. Поэтому — живой sqlite в памяти и обращение к несуществующей таблице. """ from __future__ import annotations import pytest from sqlalchemy import create_engine, text from sqlalchemy.exc import StatementError SECRET = "sup3r-secret-cookie-key-3194" def _provoke_statement_error(*, hide: bool) -> str: engine = create_engine("sqlite://", hide_parameters=hide) with engine.connect() as conn: with pytest.raises(StatementError) as excinfo: conn.execute(text("SELECT :key FROM no_such_table_3194"), {"key": SECRET}) return str(excinfo.value) def test_bind_parameters_hidden_in_exception_text() -> None: message = _provoke_statement_error(hide=True) # Отказ именно на запросе, а не на соединении — иначе проверка ниже пуста. assert "no_such_table_3194" in message assert SECRET not in message def test_falsification_secret_leaks_without_the_flag() -> None: """Обратная сторона: без флага секрет ВИДЕН — тест выше не тавтология.""" message = _provoke_statement_error(hide=False) assert SECRET in message def test_app_engine_hides_parameters() -> None: """Сам прод-движок, а не только принцип: create_engine ленив, коннекта нет.""" from app.core.db import engine assert engine.hide_parameters is True