Безопасность¶
Все платформы экосистемы стоят на одном базовом уровне безопасности. Эта страница определяет этот уровень: при добавлении новой платформы относитесь к перечисленному как к требованиям, а не к опциям.
Эшелонированная защита¶
Слои выстраиваются по принципу «ни один слой сам по себе не достаточен»:
| Слой | Защита |
|---|---|
| Edge (nginx) | TLS, HSTS, rate limit, ограничение размера тела запроса |
| Приложение (HTTP) | Security-заголовки, allow-list CORS, CSRF, таймауты |
| Приложение (логика) | RBAC, проверка прав, валидация ввода |
| База данных | RLS, параметризованные запросы |
| Аудит | Журнал аудита, связанный хеш-цепочкой |
Токен не попадает в клиентский JS¶
Шаблон BFF (Backend-for-Frontend) — основа безопасности фронтенда.
Браузер никогда не обращается к бэкенду напрямую: он говорит только с маршрутами Next.js на том же домене, а те проксируют запросы к бэкенду со стороны сервера. Токен живёт в httpOnly cookie.
Результат: XSS перестаёт быть вектором кражи токена. Даже сумев выполнить JavaScript, злоумышленник до токена не доберётся.
Сверху — двойная защита от CSRF: специальный заголовок плюс проверка origin.
Security-заголовки¶
В каждом ответе:
| Заголовок | Назначение |
|---|---|
Content-Security-Policy |
Закрывает вектор исполнения для XSS |
Strict-Transport-Security |
Принудительный HTTPS (HSTS) |
Cross-Origin-Opener-Policy |
Изоляция от межоконных атак |
Cross-Origin-Embedder-Policy |
Контроль внешних ресурсов |
Cross-Origin-Resource-Policy |
Ограничение использования ресурсов извне |
CORS — только по allow-list, * никогда.
Postgres Row-Level Security¶
Изоляция данных организаций и пользователей обеспечивается на уровне базы
данных, а не условием WHERE в коде приложения.
Почему: один забытый WHERE user_id = ? в коде — и данные утекают. RLS
применяет эту проверку ко всем запросам, независимо от ошибок в коде.
Boot-time enforceability guard
При запуске приложение проверяет, действительно ли RLS включён. Если политики нет или у пользователя подключения есть право обходить RLS, приложение отказывается стартовать.
Причина в том, что тихое отключение RLS — самый опасный случай: снаружи всё выглядит работающим нормально.
SQL¶
- Параметризованные запросы — никакой конкатенации строк.
- ORM нет — SQL пишется вручную поверх
pgx. Каждый запрос виден.
Rate limit и таймауты¶
| Защита | Где |
|---|---|
| Rate limit на аутентификацию (жёсткий) | Пути /login, /oauth, /auth, /api/auth |
| Общий rate limit приложения (мягкий) | Остальные пути |
| Rate limit API | Публичные API вида /v1/* |
| Таймауты HTTP-сервера | read · write · idle · header — все настроены |
| Ограничение размера тела | На edge |
Жёсткие лимиты — только на аутентификацию
Если поставить жёсткий лимит аутентификации на все пути, RSC-префетчи
Next.js будут превышать его и получать 503. Поэтому жёсткий лимит ставится
только на пути аутентификации, а на остальные — мягкий.
Управление секретами¶
- Шифрование токенов — сторонние OAuth-токены (Google Drive, Dropbox и т. п.) хранятся зашифрованными по AES-256-GCM.
- Криптографические ключи — в HSM; on-prem и облачный HSM резервируют друг друга.
- Секреты приложения — через переменные окружения, никогда не попадают в git.
Не кладите секреты в репозиторий
Серверные учётные данные, API-ключи, client secret, PIN от HSM — ничто из этого не записывается в репозиторий, скрипт или документацию. Deploy-скрипты принимают секреты только через переменные окружения.
Если секрет случайно раскрыт: (1) немедленно выполнить ротацию, (2) проверить логи доступа, (3) перенести его в систему управления секретами.
Закрытые в production endpoint'ы¶
/metrics и /swagger раскрывают внутреннее устройство и перечень endpoint'ов.
В production они закрыты bearer-токеном.
Журнал аудита¶
Связанный хеш-цепочкой журнал, работающий только на добавление. Каждая запись содержит хеш предыдущей.
Смысл: запись в середине невозможно удалить или изменить — цепочка разорвётся, и проверка целостности не пройдёт. Читают только администраторы; для проверки целостности есть отдельная операция.
Подпись и неотрекаемость¶
Действия с юридическими последствиями требуют подписи PIN2 — аутентификации (PIN1) недостаточно. Подробности на странице Аутентификация и права.
Закрытый ключ подписи разделён по схеме 2-of-2 threshold ECDSA — ни одна из сторон не может поставить подпись в одиночку.
Тестирование¶
- Модульные тесты — бизнес-логика и проверки прав.
- Интеграционные тесты на testcontainers — с настоящими PostgreSQL/Redis, проверяющие RLS по-настоящему.
- Тесты golden vector — совместимость криптографии на уровне протокола.
Чек-лист по безопасности¶
Перед выходом новой платформы в production:
- [ ] TLS + HSTS включены, сертификаты обновляются автоматически
- [ ] Все security-заголовки настроены (CSP · HSTS · COOP · COEP · CORP)
- [ ] Allow-list CORS — без
* - [ ] Rate limit: жёсткий на аутентификации, мягкий на остальном
- [ ] Все таймауты HTTP-сервера настроены
- [ ] RLS включён, boot-time guard работает
- [ ] Все запросы параметризованы
- [ ] Токены в httpOnly cookie, в клиентский JS не попадают
- [ ] Двойная защита от CSRF
- [ ]
/metrics,/swaggerзакрыты - [ ] Журнал аудита пишется, целостность проверяется
- [ ] Секреты через переменные окружения, в репозитории отсутствуют
- [ ] Интеграционные тесты действительно проверяют RLS