Содержание
Коротко
Код от GitHub Copilot и Claude Code часто выглядит готовым к запуску — и именно поэтому в прод уезжают одни и те же классы дыр. На Dev.to инженер Джитендра Роут описывает семь повторяющихся шаблонов: не настоящие «глупые ошибки модели», а следствие того, что ассистент оптимизирует правдоподобный рабочий пример, а не безопасную продакшен-сборку. Он выложил открытый сканер ai-vuln-scan и каталог шаблонов, чтобы ловить этот разрыв системно, а не надеяться на «лучший промпт».
Что произошло
Автор заметил, что дыры в коде с ИИ не случайны. Универсальные линтеры ищут баги вообще; здесь вопрос уже: какие промахи чаще, чем в коде, написанном человеком с нуля. Ответ простой: пример «чтобы завелось» не нуждается в менеджере секретов, параметризованном запросе и жёстком конфиге. Модель выдаёт версию, которая работает. Безопасная версия появляется, только если об этом явно попросить.
Семь шаблонов из открытого каталога:
| Шаблон | Как выглядит «удобный пример» | Что должно быть в проде |
|---|---|---|
| Секреты в коде | Ключ API «для демо» копируют как есть | Переменные окружения, хранилище секретов |
| Склейка запроса | SELECT … WHERE id = ${userId} |
Параметры / плейсхолдеры драйвера |
| Команда оболочки | exec("cmd " + arg) |
execFile() со списком аргументов |
| Слишком открытый конфиг | CORS *, выключенная проверка сертификата |
Явный список источников, проверка включена |
| Слабая криптография | MD5, Math.random() «для токена» |
Нормальные примитивы для безопасности |
| Разный доступ на похожих маршрутах | Новый маршрут «как соседний», без слоя проверки | Тот же промежуточный слой, что у остальных |
| Подробные ошибки клиенту | err.stack в ответе HTTP |
Журнал на сервере, общая фраза клиенту |
Шестой пункт автор считает самым «иишным». Человек, копируя маршрут, тащит блок целиком. Модель заново генерирует описание — и шаг с проверкой доступа легко выпадает, особенно если правки шли в разных запросах. В ревью каждая функция по отдельности выглядит нормально. В материале есть показательный обработчик Express: маршрут заказов пользователя, который на первый взгляд только читает id из адреса и отдаёт JSON. Если в том же файле остальные маршруты обёрнуты в слой проверки доступа, а этот — нет, дыра не кричит о себе синтаксисом. Она выглядит как «ещё один простой эндпоинт».
На учебном файле с намеренно вставленными дырами ai-vuln-scan нашёл 12 срабатываний (секреты, склейка запросов, маршрут без доступа, слабый генератор токена) и не дал ложных на тех же маршрутах после правки. Сейчас покрыты JavaScript, TypeScript и Python на регулярках и простой структуре кода; дальше автор хочет дерево разбора с отслеживанием потока данных и размеченный набор примеров. Каталог шаблонов он публикует отдельно от сканера: новый шаблон можно описать и обсудить, ещё не имея правила детекции. Это важно, потому что зоопарк ассистентов меняется быстрее, чем набор регулярных выражений.
Почему это важно
Команды уже встраивают ассистентов в повседневную работу. Ревью по-прежнему читает «выглядит ли функция разумно», а не «не выпал ли слой доступа при регенерации». Обычные плагины безопасности для линтера, Bandit и Semgrep часть этого ловят — но без рамки «это типичный артефакт ИИ». Именованный каталог даёт общий язык для ревью и для правил в конвейере: можно спорить с конкретным шаблоном, а не с ощущением, что «модель иногда враждебна».
Есть и организационный эффект. Если в команде уже принято «не коммитить ключи» и «не клеить SQL строками», каталог всё равно полезен как список мест, где ассистент чаще всего обходит эти правила «ради рабочего примера». Секреты в виде правдоподобного ключа, CORS * «чтобы завелось локально», MD5 «просто похешировать» — это не новая теория безопасности, а статистика того, что модель считает достаточно хорошим ответом на короткий запрос.
Отдельный сканер не заменяет нормальную архитектуру доступа. Он закрывает слепую зону: правдоподобный пример, который прошёл компилятор и ручной взгляд.
На практике
- В ревью нового маршрута сверяйте промежуточный слой доступа с соседними: если ассистент «добавлял ещё один как остальные», именно здесь чаще всего дыра.
- Запретите в политике репозитория ключи и строки подключения в исходниках, даже «временные» и «демо».
- Ищите склейку SQL и команд оболочки через шаблонные строки; требуйте параметры и массив аргументов.
- Не оставляйте в конфиге разработки
CORS *, отключённую проверку сертификата и режим отладки — ассистент не знает ваши реальные источники и сертификаты. - Для хешей паролей и токенов сессии не принимайте
MD5иMath.random()даже в «черновом» патче. - Ошибки: стек — только в журнал сервера; клиенту — нейтральное сообщение и код.
- Прогоните
ai-vuln-scan(клонировать репозиторий,npm run scan:examples) и решите, встраивать ли его рядом сSemgrep, а не вместо него.
Итог
Дыры в коде от ИИ предсказуемы: модель пишет пример, который запускается, а не сборку, которую можно выкатывать. Семь шаблонов и узкий сканер не отменяют ревью — они дают имена и автоматическую сеть на том месте, где человек хуже всего замечает выпавший слой доступа. Промпт «сделай безопасно» помогает точечно; системно работает проверка по каталогу.


