// docs / security guides / pre-launch SaaS
Чек-лист безопасности SaaS перед запуском: 35+ пунктов
До запуска продукта SaaS, созданного с помощью Cursor, Claude Code, Lovable или Bolt, осталось всего несколько дней. Этот контрольный список представляет собой аудит go/no-go, охватывающий области безопасности, которые инструменты AI постоянно пропускают и которые основателям быстрой доставки необходимо устранить, прежде чем брать деньги с клиентов. Восемь разделов, более 35 вопросов, каждый из которых можно решить за 30–90 минут. Распечатайте, вычеркните и разверните с уверенностью.
Каждый пункт ниже важен. Зеленый цвет означает, что товар отправлен и проверен; красный означает неразрешенный и блокирующий запуск. Более подробное описание каждой категории с фрагментами кода и реальными шаблонами ошибок см. в разделах How to secure an app built with AI coding tools и The vibe coding security checklist.
Изоляция данных клиентов
В мультитенантном SaaS вашей первой границей безопасности является изоляция данных. Данные каждого клиента должны быть недоступны для любого другого клиента, и это должно осуществляться на уровне базы данных, а не на уровне приложений.
- Включите безопасность на уровне строк (RLS) для каждой таблицы Supabase с помощью
ALTER TABLE public.table_name ENABLE ROW LEVEL SECURITY; ALTER TABLE public.table_name FORCE ROW LEVEL SECURITY;. FORCE не позволяет владельцу таблицы обойти ее. - Для каждой политики RLS проверьте области предиката для аутентифицированного пользователя или организации. Пример:
CREATE POLICY "users_see_own" ON public.items FOR SELECT USING (auth.uid() = user_id);. Проверьте вторую учетную запись пользователя, чтобы убедиться, что данные остаются изолированными. - При использовании Firebase / Firestore правила должны соответствовать вашей модели клиента. Не используйте
allow read, write: if true;или правила тестирования, ограниченные по времени. Используйтеallow read, write: if request.auth.uid == resource.data.owner_uid;или эквивалентное сопоставление на уровне организации. - Для доступа к файлам используйте подписанные URL-адреса или кратковременные токены, а не общедоступные корзины. Supabase Хранилище: установите
ENABLE ROW LEVEL SECURITYв таблицеobjectsи создайте политики, которые ограничивают доступ к файлам аутентифицированному пользователю. Тестируйте загрузки от имени разных пользователей. - На уровне API каждый запрос должен включать
auth.uid()или контекст идентификатора организации. Каждый запрос к базе данных должен фильтроваться по этому контексту. Пример: нетSELECT * FROM items WHERE id = $1; всегдаSELECT * FROM items WHERE id = $1 AND user_id = auth.uid().
Выставление счетов и оплата
Интеграция Stripe — это сочетание доверия клиентов и финансовой безопасности. Неправильная конфигурация здесь означает украденные платежи, петли возврата или недостающий доход.
- Используйте live Stripe keys в производстве. Протестируйте с помощью отдельной клавиши тестового режима на этапе подготовки. Никогда не переключайте переключатель из режима тестирования в режим реального времени без окончательного сканирования в режиме реального времени.
- Проверяйте подпись веб-перехватчика для каждого входящего события:
const event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);. Выдать, если подпись не удалась. Храните секрет веб-перехватчика только в переменной среды, а не в коде. - Реализуйте идемпотентность в обработчиках веб-перехватчиков, используя таблицу базы данных с ключом
event.id. Если один и тот же вебхук прибудет дважды (так и будет), второй запуск будет пустым. Запишите строку идемпотентности в той же транзакции, что и изменение состояния. customer.subscription.updatedиcustomer.subscription.deletedнемедленно отзовите доступ. Не ждите cron. Протестируйте, отменив подписку на панели управления Stripe и проверив, что пользователь заблокирован в течение 5 секунд.- Храните в своей базе данных только клиента Stripe ID и подписку ID, а не полную карту или ключ API. Получайте состояние активной подписки от Stripe на каждой границе аутентификации (загрузка страницы, вызов API, проверка cron). Не кэшируйте статус подписки более 1 минуты.
Аутентификация и сеансы
Auth — цель злоумышленников второго порядка в SaaS. Учетная запись пользователя — это вектор данных и способов оплаты.
- Используйте
supabase.auth.getUser()на каждом защищенном маршруте, а неgetSession().getSession()считывает непроверенный файл cookie;getUser()проверяет JWT на стороне сервера. В Next.js:const { data: { user } } = await supabase.auth.getUser();перед предоставлением защищенного контента. - Установите
SameSite=Laxдля файлов cookie аутентификации (Supabase Auth делает это по умолчанию). Проверьте в DevTools → Приложение → Файлы cookie. Если вы видитеSameSite=None, добавьтеsameSite: 'Lax'в конфигурацию сеанса. - Включите MFA в своей учетной записи администратора. Для MFA, ориентированного на пользователя, проверьте его перед запуском: зарегистрируйтесь, зарегистрируйте устройство TOTP, выйдите из системы, снова войдите в систему с помощью токена TOTP, убедитесь, что оно работает.
- Срок действия токенов Magic-link истекает в течение 15 минут. Срок действия токенов сброса пароля истекает в течение 1 часа. Токены сеанса (JWTs) могут жить дольше (24 часа–7 дней), но их необходимо проверять при каждом использовании. Проверьте настройки вашего провайдера аутентификации по умолчанию.
- Проверка полноты выхода: после того, как пользователь нажимает кнопку выхода, браузер удаляет сеанс аутентификации, сервер отзывает все токены, и пользователь не может получить доступ к защищенным страницам. В Supabase: позвоните
await supabase.auth.signOut()и убедитесь, что JWT больше не действителен при следующем запросе.
PII и соблюдение требований
Если вы собираете адрес электронной почты, имя, платежную информацию или любые PII, у вас есть юридические обязательства: минимизация данных, безопасное хранение, удаление по требованию и готовность DPA.
- Напишите и опубликуйте политику конфиденциальности (необязательно, даже для независимого SaaS). Укажите, какие данные вы собираете, почему, как долго вы их храните, а также права пользователя (доступ, исправление, удаление). Используйте шаблон из Termly или аналогичный, но настройте его.
- Реализуйте конечную точку удаления учетной записи API, которая удаляет PII из базы данных. Проверьте это: создайте учетную запись, добавьте данные, удалите учетную запись, убедитесь, что данные исчезли (используйте прямую проверку базы данных).
- Для обеспечения соответствия GDPR / CCPA отвечайте на запросы субъектов данных (доступ/исправление/удаление) в течение 30 дней. Документируйте свой процесс. Если ваше приложение основано на EU- или обслуживает EU пользователей, необходимо дополнение к данным Processing (DPA) с Stripe, Supabase и любым процессором.
- Шифруйте конфиденциальные поля в состоянии покоя (пароли хешируются вашим провайдером аутентификации; но для токенизации кредитной карты, ключей API и секретов следует использовать
pgcryptoили внешнее хранилище). Никогда не храните номера кредитных карт в открытом виде (вместо этого используйте токенизацию Stripe).
Оперативная готовность
Безопасность постоянная. Реагирование на инциденты, мониторинг и Runbook начинаются еще до первого дня.
- Настройте страницу статуса (Statuspage.io, Uptime Robot или простой index.html). Клиенты должны знать, есть ли у вас сбой. Сообщайте об этом при каждом происшествии.
- Задокументируйте и протестируйте ротацию дежурств. Кто просыпается по сигналу в 2 часа ночи? У кого есть ключи развертывания? Кто может отозвать скомпрометированный токен? Задокументируйте это и проведите противопожарные учения перед запуском.
- Напишите инструкцию по реагированию на инциденты безопасности: что делать, если клиент сообщает о взломе, если вы потеряете ключ, если служба выйдет из строя. Распространите его среди своей команды. Протестируйте один сценарий (e.g., смоделируйте утечку ключа), чтобы убедиться, что план работает.
- Процедуры резервного копирования и восстановления должны быть проверены, а не теоретически. Можно ли восстановить из резервной копии? Время это. Supabase: включить автоматическое резервное копирование (7 дней хранения в бесплатном режиме, 30 дней в платном режиме). Тестируйте восстановление в отдельном проекте ежеквартально.
- Включите ведение журнала аудита для привилегированных операций: Stripe вход в панель управления, Supabase вызовы администратора API, изменения схемы базы данных, сверка платежей. Инструменты: CloudTrail (AWS), журналы аудита Supabase, расширение PostgreSQL
pgaudit.
Внешняя поверхность атаки
Ваша граница API находится под постоянным контролем злоумышленников. Заблокируйте его до того, как попадет вредоносный трафик.
- Ограничьте скорость для каждой общедоступной конечной точки. Пример: 100 запросов в минуту на IP при регистрации, 10 запросов в минуту при сбросе пароля. Используйте Vercel KV, Redis или аналогичный. Ошибка с 429 (слишком много запросов).
- Добавьте CAPTCHA (hCaptcha или reCAPTCHA) для регистрации и конечных точек сброса пароля, чтобы победить ботов. Прежде чем принять запрос, проверьте серверный токен.
- Используйте WAF (брандмауэр веб-приложения), если он доступен: Cloudflare, Vercel брандмауэр веб-приложения или AWS WAF. Автоматически блокируйте известные вредоносные IP-адреса и шаблоны.
- Сканируйте открытые конечные точки API. Ежемесячно запускайте пассивное сканирование FixVibe рабочего домена. Просмотрите результаты открытых маршрутов отладки, самоанализа GraphQL, утечки ключей API или раскрытия конфигурации.
- Меняйте учетные данные (API ключи, OAuth токены, пароли базы данных) ежеквартально. Документируйте процедуру ротации и автоматизируйте ее, где это возможно.
Наблюдаемость и протоколирование
Если что-то пойдет не так, журналы станут вашей криминалистической записью. Настраивайте их с первого дня.
- Централизуйте журналы: журналы Supabase, журналы Vercel, журналы приложений и журналы аутентификации на единой информационной панели (Datadog, LogRocket или локальный ELK). Доступен для поиска, хранится не менее 90 дней.
- Оповещение о событиях безопасности: повторяющиеся неудачные входы в систему (возможный захват учетной записи), необычное использование API (возможное парсинг), всплески ошибок (возможная атака или законный инцидент). Установите пороговые значения и интеграцию со Slack.
- Создавайте журналы аудита для каждой привилегированной операции: изменения ролей пользователей, создание новой учетной записи администратора, добавление способов оплаты, изменение области действия ключей API. Храните их отдельно от журналов приложений с неизменяемым сроком хранения.
Окончательная проверка
Прежде чем объявить, запустите полное сканирование FixVibe и просмотрите результаты службой безопасности.
- Запустите FixVibe Pro активное сканирование вашего рабочего домена. Настройте свой домен для активного тестирования (DNS TXT или HTTP проверка файлов). Разрешите сканирование и просмотрите все результаты, особенно критические и высокой степени серьезности. Исправьте или примите каждое из них явно.
- Включите запланированное повторное сканирование: план Pro → 3 часа, 6 часов, 12 часов или ежедневно. План Unlimited → 6 часов, 12 часов, ежедневно, каждые 2 дня или еженедельно. Сопряжение с проверками active IDOR walking, SQL injection и reflected XSS на подтвержденном домене.
- Настройте веб-перехватчики: подключитесь FixVibe к Slack или отправьте электронное письмо, чтобы важные сведения вызывали оповещения в режиме реального времени. См. /docs/webhooks для настройки.
- Выполните окончательную ручную проверку кода, сосредоточив внимание на ошибках в /docs/security-guides/ai-generated-code-security-scanner: секреты в пакетах, RLS/rules, границы аутентификации, CSP, размещение промежуточного программного обеспечения. Используйте vibe coding security checklist в качестве шаблона обзора.
День запуска
Вы очистили контрольный список. Развертывайте с уверенностью. После запуска активно отслеживайте: проверяйте результаты FixVibe ежедневно в течение первой недели, отвечайте на оповещения в течение 1 часа и следите за расписанием сканирования. Пошаговое руководство по усилению защиты с фрагментами кода см. в разделе How to secure an app built with AI coding tools.
