Skip to content

Безопасность

Пароли

  • bcrypt, cost 12 — единственный принятый способ хеширования паролей клиентов.
  • Timing-safe вход — фиктивное сравнение bcrypt выполняется даже когда email не существует, поэтому путь входа занимает одинаковое время, существует ли пользователь. Это предотвращает перебор пользователей и timing-атаки.

API-ключи

  • HMAC-SHA256 — сервер хранит HMAC-SHA256(secret), никогда не сам секрет.
  • Ротация двух секретовAPI_KEY_SERVER_SECRET и API_KEY_SERVER_SECRET_PREV позволяют плавно ротировать секрет на сервере, не инвалидируя живые ключи.
  • Сравнение за постоянное время — подписи ключей и вебхуков сравниваются через crypto.timingSafeEqual.
  • Raw-ключ показывается один раз — исходное значение возвращается только при создании и не может быть восстановлено.

Сессии

  • Cookie runne_session: HttpOnly, SameSite=Lax, Secure в production, Max-Age 24ч.
  • Отзыв по jti — logout пишет jti сессии в denylist Redis с оставшимся сроком жизни токена; каждый запрос перепроверяет его.
  • JWT-claims валидируются, а claim isAdmin не используется для авторизации — admin-проверки читают строку клиента из базы.

CSRF (fail-closed)

Небезопасные методы (POST, PUT, PATCH, DELETE) защищены allowlist-ом Origin:

  • Origin присутствует, но не разрешён → 403.
  • Origin отсутствует, но есть cookie сессии → 403 (fail-closed).
  • Origin отсутствует и cookie нет → разрешено (вебхуки, x-api-key, server-to-server).

Allowlist выводится из FRONTEND_URL (через запятую).

Rate limiting

  • По API-ключу — скользящее окно (Redis Lua; in-memory fallback) на chat completions.
  • По IP — auth rate limiting на login (10/мин) и register (5/мин) против перебора учётных данных.

Изоляция воркспейсов

  • Каждый запрос в разрезе воркспейса проверяет владение (workspace.customer_id == session.customer_id); несовпадение возвращает 403/404.
  • Приостановленные клиенты и воркспейсы отклоняются шлюзом до обработки.

Финансовая безопасность

  • Атомарные операции: обновление баланса + вставка в реестр в одной транзакции.
  • Условные UPDATE … WHERE предотвращают перерасход и двойное зачисление.
  • Идемпотентность вебхука (проверка статуса + условное обновление + уникальный индекс) предотвращает двойное зачисление.
  • Отправка чека идемпотентна и best-effort (повторяется cron-ом, никогда не роняет вебхук).

Известные ограничения (beta)

  • Скоуп models:read пока не применяется (каталог моделей публичный).
  • Поля квоты, кроме tokens_per_month, заявлены, но не применяются.
  • Подпись вебхука опирается на YOOKASSA_WEBHOOK_SECRET; ротируйте его вместе с серверными секретами.

Связанное