Безопасность вайбкодинг-проекта
Агент из тем «Вайбкодинг: сайты» и «Вайбкодинг: интерфейсы» доводит прототип до реального продукта быстрее, чем когда-либо. Но скорость сборки не означает автоматическую безопасность результата. Агент по умолчанию оптимизирует под «работает и выглядит правильно», а не под «выдержит недобросовестного пользователя». Если ты раньше не думал о безопасности вообще (это была зона разработчика), это нормально. Навыки security-инженера здесь не нужны. Нужно знать, какие вопросы задать агенту, прежде чем показывать проект реальным людям или клиенту. Ниже короткий чек-лист ровно для этого.
Как обычно теряют вайбкодинг-проект за одну ночь
Три самых частых сценария. Они не гипотетические, а типовой набор ошибок, через который проходят почти все в начале:
- Секретный ключ API утёк в публичный код. Ключ от платной модели, платёжной системы или базы данных оказывается прямо в коде фронтенда или закоммичен в публичный репозиторий на GitHub. Такие ключи ищут автоматически, ботами, которые специально сканируют GitHub. Любой, кто найдёт ключ, может потратить весь платный лимит владельца за считаные часы. Счёт за API приходит уже после того, как ущерб нанесён.
- База данных открыта для любого запроса. Данные пользователей (email, история заказов, личные сообщения) технически лежат в облачной базе, но правила доступа к ней не настроены. Любой человек, зная только адрес проекта, может напрямую прочитать или изменить чужие данные, даже не заходя в само приложение.
- Админ-раздел доступен без проверки, кто в него зашёл. Страница управления заказами, пользователями или контентом существует по предсказуемому адресу (
/admin). Но она не проверяет, действительно ли зашедший — администратор, а не случайный посетитель, вручную набравший адрес.
Все три сценария объединяет одно. Это не сложная хакерская атака. Агент сделал рабочий прототип, а его не спросили явно: «а что будет, если сюда придёт недобросовестный человек?» Сам агент этот вопрос себе не задаёт, если его не попросить.
Чек-лист перед тем, как показать проект кому-либо за пределами своего компьютера
- Секреты не в коде — и не в браузере. Ключи API, пароли и токены доступа хранятся в файле переменных окружения (обычно
.env), который исключён из git через.gitignore. Но для фронтенд-проекта этого мало. Переменные с префиксамиVITE_,NEXT_PUBLIC_,REACT_APP_попадают в собранный код сайта, а любой ключ, который браузер отправляет сам, виден во вкладке Network. Поэтому раздели ключи на два вида. Секретные — OpenAI и Anthropic, Stripe secret, Supabase secret (раньшеservice_role) — живут только на сервере. Публикуемые — Supabase anon/publishable, Stripe publishable — можно отдавать в браузер, они для этого и сделаны. - В собранном бандле нет ни одного секретного ключа. Проверь это после сборки, а не по исходникам: именно бандл уходит в браузер каждому посетителю.
- В консоли провайдера выставлен лимит расходов, на каждый проект — отдельный ключ. Это самое дешёвое средство от сценария «потратят весь лимит»: даже если ключ утёк, ущерб упрётся в потолок, а по алерту ты узнаешь об утечке раньше счёта. Отдельный ключ на проект можно отозвать, не ломая остальные.
- Эндпоинт к платной модели защищён. Эндпоинт, который ходит к платной модели от имени сервера, сам требует входа или хотя бы ограничивает число запросов с одного пользователя/IP. Иначе ключ не нужен: бюджет потратят через твою же кнопку. Если в продукте есть ИИ-функция, читающая чужой текст, — см. про prompt injection в «CLI и терминальные ИИ-агенты».
- Права доступа к базе данных настроены явно, а не оставлены «как получилось». У Postgres-баз вроде Supabase есть row-level security, у Firebase — security rules: в обоих случаях правила доступа нужно включить явно. Row-level security — это построчные правила, кто что может читать и менять. Если его не включить явно, база по некоторым настройкам может оказаться читаемой кем угодно.
- Все чувствительные страницы и действия проверяют авторизацию. Не только страница логина. Каждый эндпоинт и каждая админ-функция проверяют, что запрос пришёл от того, кому это разрешено. Полагаться на то, что «обычный пользователь просто не знает этот адрес», нельзя.
- Пользовательский ввод не выполняется как код. Форма, куда пользователь что-то вводит, не должна напрямую попадать в запрос к базе данных или в команду сервера без проверки. Это классический вектор атаки (SQL-инъекция и похожие). Современные библиотеки от него защищают по умолчанию, но только если агент использует их правильно, а не собирает запрос вручную склеиванием строк.
- Зависимости проекта без известных уязвимостей. Библиотеки, которые агент подключил к проекту, могут содержать уже известные и задокументированные дыры в безопасности. Это проверяется одной командой (
npm auditдля JavaScript-проектов и аналоги для других языков). Попроси агента прогнать её и показать результат. - HTTPS включён, а не только HTTP. Современные сервисы деплоя (тема «Вайбкодинг: сайты», раздел «Деплой») обычно включают это автоматически. Всё равно проверь в адресной строке после публикации, а не считай само собой разумеющимся.
Как поставить задачу агенту
Хорошая новость: почти весь этот чек-лист можно не проверять руками самому. Отдай его агенту как явную задачу перед деплоем:
Прогони по этому проекту аудит безопасности перед публикацией: проверь, нет ли секретных ключей прямо в коде, настроены ли явные правила доступа к базе данных, защищены ли админ-страницы проверкой авторизации, и есть ли известные уязвимости в зависимостях. Покажи список найденного и предложи, что почини первым
Повторяй эту проверку не один раз в конце, а каждый раз, когда в проект добавляется что-то новое, что работает с данными пользователей или деньгами: форма, платёж, личный кабинет. Так проще заметить конкретную причину проблемы, чем разбирать накопленный за месяц ворох изменений разом.
Отдельная страховка — для своей машины, а не для продакшена: подстраховаться можно не только вручную перед каждым деплоем, но и автоматически. Hook на PreToolUse (тема «Терминальные агенты: настройка под себя») может блокировать явно опасные команды ещё до их выполнения агентом, даже если про ручной чек-лист в моменте забыли. Это не замена ручному аудиту выше, а дополнительный барьер поверх него.
Что делать, если ключ всё-таки утёк
Если стало известно, что секретный ключ оказался в публичном месте, не паникуй, но действуй быстро и в правильном порядке. Сначала отзови (revoke) утёкший ключ в панели сервиса, который его выдал, и выпусти новый. Только потом разбирайся, как он туда попал и как убрать его из истории git. Пока ключ не отозван, любая правка кода не помогает: старый ключ продолжает работать для того, кто его уже нашёл. После того как новый ключ выпущен, саму зачистку можно поручить агенту:
Проверь весь этот проект и историю git на упоминания вот этого утёкшего ключа: [первые и последние несколько символов ключа, не весь ключ целиком] — покажи все файлы и коммиты, где он встречается, чтобы я знал, что ещё нужно почистить
Примеры команд для практики
Прогони аудит безопасности перед публикацией.
1) Секреты: найди ключи в коде и в переменных с префиксами VITE_/NEXT_PUBLIC_/REACT_APP_. Supabase anon/publishable и Stripe publishable — норма; секретные Supabase (sb_secret_…, раньше service_role), sk-… и прочие секретные во фронтенде — критично.
2) База: если политики RLS есть в миграциях — проверь их; если нет — так и напиши и дай SQL-запрос, которым я сам проверю в Supabase, что RLS включён на всех таблицах.
3) Авторизация на админ-страницах и API-роутах.
4) npm audit — критичные отдельно.
Ничего не исправляй, только список с путями к файлам.
RLS-политики, настроенные в дашборде Supabase, агент из папки проекта не видит. А публичный anon-ключ он часто ошибочно помечает как утечку. Поэтому промпт заранее разводит, что норма, а что критично, и просит SQL для проверки базы.
Объясни простыми словами, что такое row-level security в Supabase и зачем это нужно, как будто я никогда не занимался бэкендом
Проверь эту форму обратной связи: может ли пользователь ввести туда что-то, что сломает или обманет сервер, а не просто оставит сообщение
Запусти проверку зависимостей проекта на известные уязвимости и объясни, какие из найденных проблем реально критичны, а какие можно отложитьВозьми любой свой вайбкодинг-проект, который уже подключён к базе данных или содержит хотя бы один API-ключ. Попроси агента прогнать по нему аудит безопасности из этой темы. Прочитай список найденного целиком, даже если ничего критичного не нашлось: так ты один раз увидишь, как выглядит такой отчёт на практике. Критичные находки исправь или запиши, когда исправишь.
Источники
- API keys — Supabase Docssupabase.com
publishable и secret ключи, что можно отдавать в браузер
- Row Level Security — Supabase Docssupabase.com
без RLS таблица доступна на чтение и запись
- Env Variables and Modes — Vitevite.dev
переменные VITE_ попадают в клиентский бандл
- How to use environment variables in Next.jsnextjs.org
переменные NEXT_PUBLIC_ встраиваются в JS для браузера
- npm-audit — npm Docsdocs.npmjs.com
проверка зависимостей на известные уязвимости
- Hooks reference — Claude Code Docscode.claude.com
PreToolUse может блокировать вызов инструмента
Нашёл ошибку или устаревший факт? Напиши: hey@iskra.guide