Типичная ошибка: защита включена на главной таблице и забыта на соседних
GET /rest/v1/profiles?select=*
Ответ базы: 200, пришло 412 записей — телефоны и заметки всех пользователей. Запрос отправлен из браузера, без пароля от базы, вторым аккаунтом.
Браузер показывает то, что ему велели показать. База отвечает любому, кто обратился к ней напрямую по адресу.
Правило написано на каждой таблице
GET /rest/v1/profiles?select=*
Ответ базы: отказ, ноль строк. Построчная защита на таблице говорит, что второй аккаунт видит только свои записи.
Починка этой дыры в сервисе Moltbook заняла два выражения на языке базы. Снаружи ушли 1,5 миллиона токенов.
Время от времени вы прогоняете код через агента с вопросом про уязвимости. Каждое обновление модели даёт повод прогнать ещё раз, ролики на эту тему смотрятся с интересом. Одного не хватает: списка, который заканчивается, и признака, по которому можно сказать «на сегодня закрыто». Проверка по наитию имеет свойство расширяться бесконечно и при этом пропускать ровно то, что ломает такие сервисы чаще всего.
Ниже пять практик на один вечер и один постоянный гейт после него. Обещание сознательно скромное: после прохождения сервис становится предсказуемым и теряет самые дешёвые для взлома дыры. Слов «теперь вы защищены» здесь не будет ни в одной секции. Порядок практик задан тем, что ломается чаще: OWASP Top 10 в редакции 2025 года ставит на первое место нарушение контроля доступа, на второе ошибки конфигурации.
Материал обкатан на живом сервисе: на менторской сессии мы прошли по этому списку сервис моего ученика, собранный агентом и уже принимающий записи реальных клиентов. Список закончился, находок было 58 — двенадцать серьёзных, двадцать шесть средних, двадцать мелких. Каждая стала задачей с датой, а вопрос «делать ли ещё что-то» получил письменный ответ вместо тревоги.
Слова «теперь вы защищены» здесь не будет ни в одной секции.
обещание гайда — сознательно скромное
Повод для беспокойства измерен
Veracode в отчёте GenAI Code Security за 2026 год показывает две цифры рядом. Синтаксическая корректность сгенерированного кода превышает 95%, а доля безопасных решений держится около 55%. То есть примерно в 45% случаев при наличии выбора берётся небезопасный вариант. Escape.tech в октябре 2025 просканировала более 5 600 приложений, собранных на платформах вайбкодинга: 2 038 критичных уязвимостей, более 400 утёкших ключей, 175 случаев открытых персональных данных. Выборка перекошена в сторону одной платформы, поэтому переносить проценты на весь вайбкодинг честно нельзя, но порядок проблемы виден.
| Сервис и дата | Что произошло | Чем кончилось |
|---|---|---|
| Lovableмай 2025, CVE-2025-48757 | Приложения выпускались с базой без построчной защиты, критичность 9,3 из 10. Посторонний читал и писал любые таблицы обычным запросом | Больше 170 живых приложений с открытой базой. Платформа не выпустила исправление: исправлять пришлось каждому владельцу у себя |
| Moltbookянварь 2026 | Ключ приложения нашли в коде страницы за минуты, построчная защита не была включена нигде | Наружу ушли примерно 1,5 миллиона токенов доступа и 35 тысяч почтовых адресов. Починка — два выражения на языке базы |
| Tea Appиюль 2025 | 72 тысячи фотографий, включая снимки документов, лежали в забытом хранилище прошлой версии продукта | Хранилищем никто не пользовался, поэтому его никто не проверял. Данные, которые вы не собрали и вовремя удалили, не участвуют ни в одной утечке |
| EnrichLeadмарт 2025 | Соло-основатель публично гордился продуктом без единой строки кода руками. Оплата проверялась в браузере, лимита на частоту запросов не было | Через два дня сервис разобрали, ещё через неделю закрыли. Случай подтверждается постом самого основателя: показательная история, не доказательство |
Все четыре случая укладываются в две первые категории OWASP Top 10:2025 — нарушение контроля доступа и ошибки конфигурации
Клиент открывает вашу страницу записи и видит только свою карточку. Ощущение безопасности рождается именно здесь и почти всегда обманывает. Защита опубликованного продукта живёт в четырёх слоях, и большинство дыр возникает из-за путаницы между ними.
Слова, которые встретятся дальше:
Пять практик на один вечер
- Закрытая база. Построчная защита на каждой таблице, служебный ключ только на сервере, старые хранилища — списком с решением.
- Второй аккаунт. Чужой номер в адресе под тест-аккаунтом; сервер обязан вернуть отказ. Единственный шаг, который автоматика не заменяет.
- Секреты, видимые из браузера. Поиск по сборке страницы и истории репозитория; отзыв ключа идёт раньше чистки истории.
- Ревью по перечню. Один фиксированный список категорий вместо «посмотри уязвимости»; находки сортируются по доступности постороннему.
- Гейт. Ревью на каждой заявке на слияние, предупреждения зависимостей сами, календарь из трёх строк. Разобран отдельной секцией ниже.
Практика 1. Закрытая база: посторонний не читает чужие записи
Типичная ошибка: приложение опубликовано, публичный ключ в коде страницы, защита включена на главной таблице заказов — и забыта на таблицах профилей и отзывов
Пока условие не написано, таблица открыта всем, у кого есть публичный ключ приложения. Сделать прямой запрос умеет любой человек с браузером и десятью минутами свободного времени.
- Таблица без правила открыта по умолчанию. Условие доступа появляется только тогда, когда его написали.
- Служебный ключ проходит мимо всех правил. В Supabase это service_role: место — серверная часть и переменные окружения.
- Правило пишется на каждую таблицу отдельно. Одна забытая таблица открывает свои строки полностью.
- Платформа сама показывает список дыр. Security Advisor в панели Supabase перечисляет таблицы без защиты, раз в неделю приходит письмо с той же сводкой.
- Объём хранения проверяется вместе с доступом. Старые копии и хранилище прошлой версии живут дольше памяти о них.
Мой сервис [ВСТАВИТЬ_НАЗВАНИЕ] работает на [ВСТАВИТЬ_ПЛАТФОРМУ_БАЗЫ, например Supabase] и уже принимает данные реальных пользователей. Проведи инвентаризацию доступа к базе. Ничего не меняй. 1. Перечисли таблицы, которые сервис отдаёт наружу через API. По каждой назови файл, из которого ты её взял: файл миграции, описание схемы, настройка проекта. Таблицы, которых нет в файлах, не придумывай: вынеси их в список «посмотреть в панели». 2. По каждой скажи: включена ли построчная защита, какие политики написаны, какие роли под них попадают. Имя каждой политики выпиши целиком. 3. Для каждой незакрытой таблицы объясни обычными словами, что именно увидит посторонний человек без логина: какие поля, чьи записи, сколько строк. 4. Найди все места, где используется служебный ключ, который обходит правила. По каждому месту верни строку вида «путь к файлу : номер строки : имя переменной : сервер или браузер». Отдельно перечисли файлы, попадающие в сборку страницы, и скажи прямо, встречается ли служебный ключ хотя бы в одном из них. Само значение ключа в чат не выводи ни при каких условиях, достаточно имени переменной. 5. Верни таблицу «таблица — защита — что видит посторонний — насколько срочно» и предложи порядок закрытия. Правки покажи мне на согласование, применять их я скажу отдельно.
Готово, когда: список таблиц, отдаваемых наружу, записан файлом, и напротив каждой строки стоит имя политики; Security Advisor показывает ноль таблиц без защиты; служебного ключа нет ни в одном файле сборки и репозитория; по каждому старому хранилищу принято письменное решение — оставить или удалить.
Практика 2. Проверка вторым аккаунтом: чужая запись и чужой счёт
Типичная ошибка: платный раздел скрыт в браузере, а адрес выдачи данных отвечает всем вошедшим одинаково — независимо от оплаты и владения записью
Автоматика хорошо ищёт то, у чего есть узнаваемый образец: открытый ключ, известная дырявая библиотека. Хуже всего она ловит другое: сервис исправно проверяет, что вы вошли, и забывает проверить, что запись действительно ваша. Cobalt в отчёте AI and Pentesting Pulse за 2026 год приводит цифру: 78% опрошенных команд ловят пропуски автоматических проверок, и хуже всего автоматика справляется как раз с чужим доступом к чужому объекту. Доля команд, полагающихся только на автоматику, за год упала с 29% до 9%. Опрошены крупные компании — проценты читаются как направление.
Рядом живут две ошибки в других обличьях: проверка оплаты сделана в браузере, и сервер не ограничивает частоту запросов. Если ваш сервис ходит в платный сервис моделей от имени пользователя, посторонний может обращаться к нему без остановки и оставить вам счёт — отраслевое название denial of wallet. Ограничение частоты закрывает и перебор чужих номеров, и этот счёт.
Разбери контроль доступа в моём сервисе [ВСТАВИТЬ_НАЗВАНИЕ]. Сервис собран на [ВСТАВИТЬ_СТЕК, например Next.js на Vercel и база Supabase], публичный адрес [ВСТАВИТЬ_АДРЕС_САЙТА]. Ничего не меняй, собери отчёт. 1. Перечисли все адреса и запросы, где в параметрах есть номер объекта пользователя: запись, заказ, профиль, файл, сообщение. По каждому назови путь к файлу и номер строки, где адрес объявлен. 2. По каждому покажи строку кода, которая проверяет, что объект принадлежит спрашивающему. Если такой строки нет, напиши это прямо. 3. Найди проверки прав и проверки оплаты, которые выполняются только в браузере, и покажи, есть ли у каждой серверная пара. 4. Перечисли адреса, обращающиеся к платным сервисам и моделям, и скажи, где стоит ограничение частоты запросов, а где его нет. 5. Собери сценарий ручной проверки вторым аккаунтом ровно из трёх шагов. Для каждого шага дай готовую строку, которую я вставлю в адресную строку браузера: полный адрес моего сервиса вместе с номером объекта, взятым из моих же данных, без сокращений. Рядом с каждым адресом напиши, под каким аккаунтом его открывать, что я должен увидеть при исправном сервисе и что будет означать провал. 6. Верни таблицу «адрес — файл и строка — проверка владельца — проверка оплаты — ограничение частоты — риск». Правки покажи отдельным списком на согласование и жди моего слова.
Готово, когда: второй аккаунт заведён, три адреса из сценария открыты под ним, и на каждом сервис вернул отказ; по каждому платному действию названа серверная строка, которая проверяет оплату; после серии повторов сервис отвечает отказом.
Практика 3. Секреты в опубликованном продукте
Типичная ошибка: ключ сервиса вынесли в переменную с приставкой публичности, потому что «иначе фронтенд не видит», и сервис заработал с первого раза
Во фреймворках вроде Next.js переменная с приставкой NEXT_PUBLIC_ попадает в код страницы намеренно: слово public в её имени означает буквально «значение станет публичным». В Moltbook ключ базы нашли в коде страницы за минуты именно так. Вторая половина практики — история репозитория: даже убранный из текущей версии ключ старые версии помнят навсегда.
Порядок действий обратен интуиции: сначала отзыв и замена ключа, только потом чистка истории. Ключ, о котором знает посторонний, перестаёт быть опасным в момент отзыва; удаление строки из файла этот момент не приближает. Для служебного ключа, который обходит правила базы, отзыв обязателен даже при сомнении: его утечка равна выдаче всей базы.
Проверь, какие секреты моего сервиса [ВСТАВИТЬ_НАЗВАНИЕ] могут быть видны постороннему человеку. 1. Перечисли все переменные окружения с приставкой публичности [ВСТАВИТЬ_ПРИСТАВКУ, например NEXT_PUBLIC_]. По каждой напиши, зачем она в браузере и что произойдёт, если её узнает посторонний. 2. Проверь собранный код страниц на присутствие значений, похожих на ключи и токены, по образцам: [ВСТАВИТЬ_ОБРАЗЦЫ, например для Supabase и Stripe это sb_secret_, sb_publishable_, eyJ, sk_live_, sk_test_]. 3. Проверь полную историю репозитория теми же образцами и скажи, встречались ли похожие значения когда-либо. 4. По каждой находке верни строку «путь к файлу : номер строки : имя переменной : какой сервис открывает : что отозвать первым». Если находок нет, так и напиши, а список образцов, по которым ты искал, покажи мне на согласование. Значения найденных секретов в чат не выводи ни при каких условиях. Достаточно имени переменной, файла и строки. Ничего не меняй сам: верни отчёт и порядок действий, я подтвержу каждый шаг.
Готово, когда: у каждой публичной переменной записано обоснование; поиск по сборке и по всей истории репозитория пуст; каждый найденный ранее ключ отозван и заменён — удаления строки из файла для этого мало.
Практика 4. Официальное ревью: список вместо наития
Типичная ошибка: «прогони код на уязвимости» в свободной формулировке; отчёты каждый раз про разное, сравнить два прогона невозможно
Замена наитию появилась 6 августа 2025 года: Anthropic встроила в Claude Code команду /security-review с фиксированным перечнем категорий — внедрение команд в запросы к базе, выполнение чужого кода на странице, ошибки проверки входа, обработка данных, состояние зависимостей. Одна особенность: команда смотрит изменения текущей ветки и молчит о проблемах, которые были в коде до них. Для давно опубликованного сервиса первый полный проход делается промптом с тем же перечнем, а команда встаёт гейтом на новые изменения.
Здесь важно развести две проверки. Ревью качества отвечает на вопрос «насколько этот код удобно развивать», ревью безопасности — «что здесь сделает посторонний». Пройденное ревью качества о безопасности не говорит ничего, и обратное верно. Находки сортируются по одному вопросу: что может сделать посторонний без логина — это идёт первым; дальше доступное любому вошедшему; правки, требующие прав администратора, ждут очереди.
Зависимости входят в тот же прогон отдельным блоком. У одного из моих студентов на сервере поселился майнер, приехавший через уязвимость в подключённой библиотеке; предупреждение об этой уязвимости лежало в репозитории заранее. Уязвимость CVE-2025-29927 в Next.js позволяла подделкой заголовка пропустить весь слой промежуточной проверки; безопасны версии от 15.2.3, 14.2.25, 13.5.9 и 12.3.5.
Пройди по всему коду моего сервиса [ВСТАВИТЬ_НАЗВАНИЕ] тем же перечнем категорий, что берёт команда /security-review, и разбери находки. Ничего не меняй. Категории: внедрение команд в запросы к базе; выполнение чужого кода на странице; ошибки проверки входа и прав; небезопасная обработка данных пользователей; секреты в коде; состояние зависимостей; подробности внутренней ошибки в ответе наружу. 1. По каждой находке верни строку «путь к файлу : номер строки : категория : что сделает посторонний : сколько шагов ему нужно». 2. Разложи все находки по трём корзинам: доступно постороннему без логина; доступно любому зарегистрированному; требует прав администратора. 3. Отдельным блоком проверь зависимости: библиотеки с известными уязвимостями и версия фреймворка [ВСТАВИТЬ_ФРЕЙМВОРК_И_ВЕРСИЮ]. Номер версии возьми из файла зависимостей и назови этот файл, по памяти версию не указывай. 4. Отметь находки, которые считаешь ложной тревогой, и объясни по каждой, почему. 5. Верни план правок по порядку срочности и покажи его мне на согласование. Ничего не меняй, пока я не скажу «выполняй» по конкретному пункту. Значения найденных секретов в чат не выводи, достаточно имени переменной, файла и строки.
Готово, когда: полный проход сделан и отчёт сохранён файлом с датой; каждая находка лежит в одной из трёх корзин; доступное без логина закрыто или стало задачей с датой; версия фреймворка выписана из файла зависимостей и сверена со списком безопасных.
Гейт вместо разового вечера
Разовый аудит устаревает с первым же изменением. Ответ на вопрос «делать ли что-то ещё» звучит так: часть проверок переводится в автоматический режим и происходит без вашего участия, а на вашу долю остаётся короткий календарь.
Автоматически работают три вещи. GitHub Action claude-code-security-review прогоняет ревью на каждой заявке на слияние и оставляет замечания прямо в строках изменённого кода. Dependabot присылает предупреждения о новых уязвимостях зависимостей по мере их публикации. Письмо Security Advisors от Supabase раз в неделю приносит сводку по таблицам.
Ручной календарь короткий. Раз в неделю — просмотр пришедших предупреждений. Раз в месяц — обновление зависимостей. Раз в квартал — ревизия доступов и настоящее восстановление резервной копии, потому что копия, которую ни разу не восстанавливали, копией считается условно.
Кроме календаря есть события. Это позиция автора, не отраслевой стандарт: новый адрес, отдающий данные пользователей; подключение платежей; смена модели у агента, который пишет код; первый крупный клиент, читающий ваш ответ на вопросы про безопасность. Событие из этого списка означает повторение практик 1 и 2 в тот же день.
Отдельно готовится план на плохой день. Он пишется заранее и лежит одним файлом, потому что в момент утечки времени на сочинение порядка действий не будет.
Признак происшествия: [ЧТО Я УВИДЕЛ, например письмо о найденном ключе] Первый час: 1. Отозвать и заменить ключи: [СПИСОК_КЛЮЧЕЙ_И_ГДЕ_ОТЗЫВАТЬ] 2. Закрыть дыру или временно отключить затронутый адрес: [ЧТО ИМЕННО] 3. Зафиксировать время обнаружения и первые действия письменно. Первый день: 4. Оценить объём: чьи данные, какие поля, сколько записей. 5. Проверить журналы доступа за период: [ГДЕ ЛЕЖАТ ЖУРНАЛЫ] 6. Решить вопрос уведомления пострадавших: [КТО ГОТОВИТ ТЕКСТ] 7. Хронология одним файлом: что, когда, чьим решением; что меняем в гейте. Кому звоню: [ЮРИСТ], [ТЕХНИЧЕСКАЯ_ПОМОЩЬ], [ВЛАДЕЛЕЦ_ДАННЫХ]
Настрой постоянную проверку безопасности для репозитория [ВСТАВИТЬ_ВЛАДЕЛЕЦ]/[ВСТАВИТЬ_ИМЯ_РЕПОЗИТОРИЯ]. 1. Подготовь файл настройки для GitHub Action anthropics/claude-code-security-review так, чтобы он запускался на каждой заявке на слияние и оставлял замечания в строках изменённого кода. Верни целиком: путь к файлу и его текст. Отдельной строкой назови имя секрета с ключом доступа к модели и дай шаги, которыми я положу этот секрет через интерфейс GitHub. 2. Проверь, включён ли Dependabot и приходят ли предупреждения о зависимостях; если нет, дай шаги включения через интерфейс. 3. Собери мне календарь из трёх строк: что я смотрю раз в неделю, раз в месяц и раз в квартал. Каждую строку начинай с глагола и заканчивай адресом страницы, которую я для этого открываю. 4. Составь список событий, после которых я повторяю проверку базы и проверку вторым аккаунтом в тот же день. Секреты репозитория в чат не выводи, работай только с именами. Настройки покажи мне на согласование до применения.
Готово, когда: файл настройки Action лежит в репозитории и на пробной заявке проверка отработала; Dependabot включён; календарь из трёх строк лежит файлом и недельная строка выполнена хотя бы раз с отметкой даты; копия развёрнута в проверочной среде хотя бы один раз; в плане на плохой день не осталось ни одного места для подстановки.
Приёмка: готово, когда
Полностью пройденный контур выглядит так. Копируется одним куском — это и есть тот список, который заканчивается.
| Практика | Готово, когда |
|---|---|
| 1. Закрытая база | каждая таблица, отдаваемая наружу, закрыта правилом доступа; служебный ключ отсутствует в браузере, репозитории и переписке с агентом |
| 2. Второй аккаунт | ручная проверка выполнена и вернула отказ; каждое платное действие проверяется на сервере; обращения к платным сервисам ограничены по частоте |
| 3. Секреты | публичные переменные перечислены с обоснованием, поиск по истории репозитория чист, найденные ранее ключи отозваны |
| 4. Ревью по перечню | полный проход сделан, находки разложены по доступности постороннему, доступное без логина закрыто или стало задачей с датой |
| 5. Гейт | автоматическое ревью висит на заявках, предупреждения приходят сами, календарь из трёх строк работает, план на плохой день написан |
Пройденный список не делает сервис неуязвимым. Он даёт предсказуемость: письменный ответ на «достаточно ли того, что я делаю» и самые дешёвые дыры, закрытые раньше, чем их найдёт посторонний
Итоговая приёмка: безопасность вайбкодинг-сервиса (sereja.tech/kak-proverit-servis-na-dyry, 02.10.2026) 1 Закрытая база | каждая таблица наружу закрыта правилом; служебного ключа нет в браузере, репозитории и переписке с агентом 2 Второй аккаунт | проверка вернула отказ; оплата проверяется на сервере; обращения к платным сервисам ограничены по частоте 3 Секреты | публичные переменные с обоснованием; история репозитория чиста; найденные ключи отозваны 4 Ревью по перечню | полный проход с отчётом; находки по корзинам доступности; доступное без логина закрыто 5 Гейт | авторевью на заявках; предупреждения приходят сами; календарь из трёх строк; план на плохой день написан Живой специалист нужен, если: через вас идут платежи; храните документы, медицинские или финансовые данные; приходит крупный клиент со своим вопросником; утечка означает конец бизнеса.
В отдельных случаях нужен живой специалист по проверке защищённости: через вас идут платежи; вы храните документы, медицинские или финансовые данные; приходит первый крупный клиент со своим вопросником; утечка означает конец бизнеса.
Частые вопросы
У меня не Supabase — гайд не про меня?
Про любой сервис, где база отвечает по публичному ключу из браузера. Названия меняются, механика та же: правило на таблице, служебный ключ на сервере, чужая запись проверяется руками.
Пользователей пока нет. Делать сейчас?
Правила пишутся до первой ссылки: после публикации чинить дороже, а первая утечка не спрашивает, сколько у вас записей.
Агент сам всё проверит?
По фиксированному перечню — да. Чужую запись проверяет второй аккаунт руками. Официальная оговорка Anthropic звучит честно: команда дополняет ручную проверку и не заменяет её.
Прошёл ревью качества кода — я защищён?
Нет. Ревью качества отвечает на вопрос «насколько этот код удобно развивать», ревью безопасности — «что здесь сделает посторонний». Это разные проверки, и одна другую не покрывает.
Что с юридической стороной утечки?
GDPR требует уведомления надзорного органа в течение 72 часов и не делает исключений по размеру бизнеса. В России ответственность выросла с 30 мая 2025 года: градация штрафов по масштабу, за повторные случаи — оборотные штрафы с потолком в 500 миллионов рублей. Цифры из вторичных источников: перед решениями сверяйте с текстом закона или юристом.
Ссылки
- Supabase — Row Level Securityпервоисточник по построчной защите таблиц
- OWASP Top 10:2025категория A01 задаёт порядок практик и сценарий проверки вторым аккаунтом
- Anthropic — Claude Code Securityправа агента и оговорка о дополняющем характере ревью
- claude-code-security-reviewисходный текст проверки и образец файла настроек под свой продукт
- Cobalt — AI and Pentesting Pulse 202678% пропусков у автоматики; доля «только автоматика» с 29% до 9%
- gitleaksсканер секретов: образцы ключей и поиск по всей истории репозитория
- Как проверить нейросеть на своей задачесоседний гайд серии: эвал моделей на своей задаче
- Как агент ведёт мои деладругой гайд серии
Промпты и гейты из этого гайда работают в Personal Corp. Подробнее в боте.
Цифры: Veracode GenAI Code Security 2026; скан Escape.tech, октябрь 2025. Случаи: CVE-2025-48757 (Lovable), Moltbook, Tea App, EnrichLead, CVE-2025-29927 (Next.js). Промпты собраны по официальной документации Supabase, Anthropic и сканера gitleaks; в потоках они пока не обкатаны, первый прогон каждого стоит читать глазами. Сервис ученика в примерах не назван, его данные не использованы; запрос на первом экране — реконструкция механики, а не лог его базы.