Перейти к содержанию

Аудит безопасности

Статус: Развёрнуто в production

URL платформы: https://ziex-tryon.com
Все 41 проблема безопасности устранена или осознанно отложена. 507 тестов. Покрытие ≥97%.


Обзор

Платформа TryOn SaaS — это B2B-сервис виртуальной примерки одежды, развёрнутый по адресу ziex-tryon.com. В мае 2026 года было выявлено 41 проблема безопасности и качества кода — все были устранены или осознанно отложены с письменным обоснованием. Платформа теперь работает с 507 автоматическими тестами, покрытием кода более 97%, полной наблюдаемостью через метрики Prometheus и три дашборда Grafana, а также автоматическим CI/CD-деплоем с верификацией состояния после развёртывания.


Что было построено

Основная платформа

  1. API виртуальной примерки — Бизнесы интегрируются через REST API. Покупатели отправляют два изображения; AI возвращает результат примерки за 15–30 секунд.
  2. Мультитенантный биллинг — У каждого клиента есть аккаунт, месячный тариф, API-ключи и опциональные вебхук-коллбэки.
  3. Клиентский портал — Самообслуживание: история задач, использование vs квота, управление вебхуками.
  4. Встраиваемый виджет — Один тег <script>, автоопределение продуктов, изоляция через Shadow DOM.

Устранение проблем безопасности — 41 находка

По категориям

Категория Находок Статус
Аутентификация и управление доступом 8 Все устранены
Валидация ввода и инъекции 7 Все устранены
Инфраструктура и конфигурация 14 Устранены + 3 отложены по решению
Корректность фронтенда 7 Все устранены
Наблюдаемость и мониторинг 5 Устранены в Фазе 2

Закрытые ключевые риски

Риск До После
Инъекция вредоносных URL через вебхуки Без валидации Заблокировано: приватные IP, loopback, cloud metadata. DNS-проверка при регистрации.
Неограниченное злоупотребление API Нет лимита по IP 30 запросов/мин по IP
Брутфорс паролей Нет блокировки 5 попыток, блокировка 15 мин по IP + email
Кросс-клиентское чтение задач Без изоляции по тенантам Каждый поиск статуса фильтруется по client_id
Открытые данные мониторинга Метрики Prometheus публично доступны Заблокировано на nginx (403)
Открытые внутренние порты БД/Redis/Prometheus доступны извне Production закрывает все внутренние порты
Небезопасная загрузка изображений Нет защиты от decompression bomb Проверка магических байтов, лимит 16.7М пикселей, удаление EXIF
Перечисление пользователей по таймингу Тайминг входа раскрывал наличие пользователя Константное время сравнения на всех путях кода
Зависшие задачи воркера Нет таймаута поллинга Потолок 600 сек; устаревшие задачи автоматически переводятся в failed через 15 мин
SQL-инъекции f-string SQL в 7 местах Всё параметризовано

Текущее состояние платформы

Показатель Значение
Автоматические тесты 507+ в 26 тестовых файлах
Покрытие кода ≥97%
Открытые проблемы безопасности 0
Мониторинг Prometheus + Grafana (3 авто-подготовленных дашборда)
Алертинг Telegram (здоровье воркера, частота ошибок, доступность БД/Redis)
Резервное копирование Ежедневное автоматическое, хранение 30 дней
CI/CD lint → test → build → deploy при успехе CI
TLS Cloudflare proxy, HSTS, TLSv1.2+

Приёмка аудита

Аудит Package 10 завершён 2026-05-18. Все 44 шага E2E-браузерного тестирования прошли (Admin UI + Portal + Embed). Все проверки готовности к production прошли (health, security headers, nginx, docker-compose.prod.yml, backup, deploy.sh). Ноль предупреждений ruff.


Осознанно отложенные пункты

Эти пункты были оценены и явно отложены — они не являются открытыми проблемами.

Пункт Обоснование Остаточный риск
Восстановление пароля / email-recovery Требует email-провайдер. Восстановление администратора через прямой доступ к БД достаточно на текущем масштабе. Низкий
Самообслуживание API-ключей на портале Управляемые администратором ключи безопасны. Самообслуживание — улучшение UX для Фазы 3. Нет
Предподписанные URL загрузки S3 Текущий flow с base64 работает на данных объёмах. Нет
Rate limiting смены пароля Окно токена доступа 15 мин ограничивает поверхность атаки. Очень низкий
Горизонтальное масштабирование GPU-воркера на K8s Один сервер справляется с текущей нагрузкой. Нет

Отложено ≠ игнорируется

Каждый отложенный пункт имеет письменное обоснование и будет пересмотрен при наступлении условия-триггера (например, email-recovery — при добавлении email-провайдера; K8s — когда нагрузка потребует).


Реестр технического долга

Это известные ограничения на уровне кода, которые не блокируют запуск, но должны быть устранены в ближайших спринтах.

Проблема Влияние Усилия
avg_latency_ms не пересчитывается при CONFLICT Дашборд использования показывает задержку первой задачи клиента, не скользящее среднее Низкие — SQL-формула
Admin webhook CRUD: допущение user.id == client.id Второй admin-пользователь без соответствующей записи Client получает 404 на все операции с вебхуками Низкие — исправление запроса
Счётчик Prometheus TRYON_COMPLETED не инкрементируется Счётчик завершений на дашборде всегда равен нулю Низкие — один вызов .inc() в воркере
Node.js 20 EOL июнь 2026 Сборка фронтенда использует неподдерживаемую среду выполнения после июня 2026 Низкие — обновить базовый образ до node:22-alpine
CI diff использует HEAD~1 Обнаруживает только изменения последнего коммита; пуши с несколькими коммитами могут пропустить изменённые сервисы Средние — переключиться на diff github.event.before...after

Node.js 20 EOL

Dockerfile фронтенда использует node:20-alpine. Node.js 20 достигает конца жизни 2026-06-02. Обновите до node:22-alpine до этой даты. Изменения кода не ожидаются — Vite 5 поддерживает Node 22.


Рекомендуемая следующая фаза

Приоритизировано по бизнес-влиянию:

Фаза Пункт Оценка усилий
1 Интеграция биллинга Stripe — принудительные платные тарифы, выставление счетов 2–3 недели
2 Email-уведомления (SendGrid/Postmark) — восстановление пароля, алерты по задачам 1 неделя
3 Улучшения самообслуживания портала — создание/отзыв API-ключей, запросы на смену тарифа 1–2 недели
4 Масштабирование производительности — при достижении порогов нагрузки 3–4 недели

Предпосылка для Фазы 1

Интеграция Stripe требует email-провайдера (для подтверждений биллинга и квитанций), поэтому Фазы 1 и 2 лучше разрабатывать совместно.


Сводка архитектуры деплоя

Интернет → Cloudflare Proxy (DDoS, WAF)
         → nginx (:443, TLS 1.2+, HSTS)
         → admin-api (FastAPI, только внутренний)
         → postgres / redis (только внутренние)
         → ml-worker (внутренний, BRPOP loop)
         → fal.ai FASHN v1.5 (внешний AI)

Мониторинг: Prometheus → Grafana (внутренний)
Алертинг:   AlertManager → Telegram Bot
Бэкапы:     pg_dump → /opt/tryon-saas-backups/ (ежедневно, хранение 30 дней)
CI/CD:      GitHub Actions → SSH-деплой при успехе CI

Все внутренние сервисы (postgres, redis, prometheus, grafana) не открыты в интернет. В production через UFW открыты только порты 22, 80 и 443.