Александр Руин

Консультант по проектированию AI‑систем

Александр Руин — консультант по проектированию систем. Помогаю спроектировать архитектуру, оценить риски и выстроить прозрачный процесс — от выбора технологий до сопровождения. Рутину берут на себя AI‑исполнители. Направления: автоматизация, интеграции, AI‑продукты.

Безопасность AI-сгенерированного кода: 7 уязвимостей, которые мы находим в каждом третьем проекте

Cursor написал форму авторизации. Форма работает. Но в ней SQL-инъекция, нет rate limiting и JWT хранится в localStorage вместо httpOnly cookie. Это не теория — исследование CMU и Johns Hopkins (2025) показало: до 90% AI-сгенерированного кода содержит уязвимости из OWASP Top 10.

Мы ревьюим вайбкодинг-проекты через Vibers и видим это своими глазами. Ниже — семь уязвимостей, которые встречаем чаще всего. Со всеми примерами кода до и после исправления.

Ключевые выводы: - 90% AI-кода содержит уязвимости OWASP Top 10 (CMU/Johns Hopkins, 2025) - Самые частые: неправильная авторизация, отсутствие rate limiting, небезопасное хранение JWT - SAST-сканеры ловят паттерны, но пропускают IDOR и ошибки бизнес-логики - Полный OWASP-аудит от Vibers — 30 000 ₽ разово или от 5 000 ₽/мес

Почему AI генерирует небезопасный код?

Copilot не знает, что eval() опасен в контексте вашего API. Claude Code не проверяет, что JWT хранится в localStorage. Модели воспроизводят паттерны из обучающих данных — включая небезопасные. На GitHub 70% кода написано без явного учёта безопасности — именно на этом обучались модели.

Безопасность нужно запрашивать явно. И даже тогда результат требует проверки: AI не понимает контекст вашего приложения — только паттерны.

7 уязвимостей из реальных проектов

1. IDOR — доступ к чужим данным через предсказуемый ID

Как AI создаёт: генерирует CRUD endpoint, принимает userId или resourceId из запроса без проверки прав.

// AI сгенерировал — выглядит корректно:
app.get('/api/documents/:id', authMiddleware, async (req, res) => {
  const doc = await db.documents.findById(req.params.id);
  res.json(doc);
});

// После ревью — проверка владельца:
app.get('/api/documents/:id', authMiddleware, async (req, res) => {
  const doc = await db.documents.findById(req.params.id);
  if (!doc || doc.ownerId !== req.user.id) {
    return res.status(403).json({ error: 'Access denied' });
  }
  res.json(doc);
});

Что грозит: любой авторизованный пользователь читает документы других пользователей, перебирая id=1,2,3...


2. JWT в localStorage — уязвимость XSS

Как AI создаёт: хранит токены в localStorage "для простоты" — это паттерн из большинства туториалов на GitHub.

// AI сгенерировал (frontend):
localStorage.setItem('token', response.data.token);
// При каждом запросе:
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }

// Правильно — httpOnly cookie (backend):
res.cookie('token', jwtToken, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  maxAge: 7 * 24 * 60 * 60 * 1000
});

Что грозит: одна XSS-инъекция через user-generated content — и всё: злоумышленник читает токен через document.cookie... нет, через localStorage.getItem('token') — именно поэтому httpOnly и защищает.


3. Нет rate limiting на критических endpoint'ах

Как AI создаёт: реализует login, регистрацию, сброс пароля — без ограничений на количество попыток.

// AI сгенерировал — нет защиты от перебора:
app.post('/auth/login', async (req, res) => {
  const user = await db.users.findByEmail(req.body.email);
  const valid = await bcrypt.compare(req.body.password, user?.passwordHash);
  if (!valid) return res.status(401).json({ error: 'Invalid credentials' });
  // ...
});

// После добавления rate limiting:
const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 минут
  max: 5,                    // максимум 5 попыток
  message: { error: 'Too many login attempts, try again in 15 minutes' }
});

app.post('/auth/login', loginLimiter, async (req, res) => {
  // ...
});

Что грозит: брутфорс пароля за минуты. Особенно опасно для admin-панелей и B2B-приложений.


4. SQL-конкатенация вместо параметризации

Как AI создаёт: особенно часто в Python-проектах с сырыми запросами, когда разработчик просит "просто написать запрос".

# AI сгенерировал (встречаем в каждом втором Python-проекте):
def get_user(username):
    query = f"SELECT * FROM users WHERE username = '{username}'"
    return db.execute(query)

# Правильно:
def get_user(username):
    return db.execute("SELECT * FROM users WHERE username = %s", (username,))

Что грозит: классическая SQL-инъекция. username = "' OR '1'='1" — и злоумышленник получает все данные таблицы.


5. Секреты в коде и .env в репозитории

Как AI создаёт: копирует паттерны из обучающих данных, где API-ключи иногда захардкожены "для примера".

// AI сгенерировал:
const stripe = require('stripe')('sk_live_abc123xyz...');
const OPENAI_KEY = 'sk-proj-...';

// Правильно:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const OPENAI_KEY = process.env.OPENAI_API_KEY;

А ещё: разработчики часто коммитят .env файл — AI не предупреждает. Мы добавляем .gitignore с .env в PR.


6. CORS открыт для всех

Как AI создаёт: настраивает cors({ origin: '*' }) "для простоты разработки" — и это уходит в прод.

// AI сгенерировал:
app.use(cors({ origin: '*' }));

// После ревью:
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') || ['https://yourapp.com'];
app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) callback(null, true);
    else callback(new Error('Not allowed by CORS'));
  },
  credentials: true
}));

Что грозит: любой сайт может делать запросы к вашему API от имени авторизованного пользователя (CSRF через CORS).


7. Stack trace в ответах API

Как AI создаёт: добавляет глобальный error handler, который возвращает полный стектрейс в JSON-ответе.

// AI сгенерировал:
app.use((err, req, res, next) => {
  res.status(500).json({ error: err.message, stack: err.stack });
});

// После ревью:
app.use((err, req, res, next) => {
  logger.error({ err, url: req.url, method: req.method }); // логируем на сервере
  const isDev = process.env.NODE_ENV === 'development';
  res.status(err.status || 500).json({
    error: isDev ? err.message : 'Internal server error',
    ...(isDev && { stack: err.stack })
  });
});

Что грозит: stack trace содержит пути файлов, версии зависимостей, иногда части конфига — готовая карта для атаки.


Почему автоматических сканеров недостаточно

Semgrep и Bandit найдут SQL-конкатенацию и cors('*') — это паттерны в их базе правил. Они не найдут IDOR (нужно понимать, кому принадлежит ресурс), race conditions (нужно понимать конкурентность) и неправильную бизнес-логику в авторизации.

Наш опыт: автосканеры покрывают 30–40% проблем безопасности. Остальные 60% требуют человека, который читает ТЗ и понимает контекст.

Три шага защиты AI-кода перед деплоем

Шаг 1. Запустите SAST-сканер (Semgrep, Bandit для Python, npm audit для Node.js) — бесплатно, 5 минут настройки, ловит паттерны.

Шаг 2. Добавьте gitleaks в CI — проверка на секреты в коде при каждом пуше.

Шаг 3. Подключите Vibers для полного OWASP-аудита. Человек проверяет IDOR, авторизацию, бизнес-логику — то, что автоматика пропускает. Для стартапов с ограниченным бюджетом — читайте code review без штатного senior.

FAQ

SAST-сканеры достаточны? Для паттернов — да. Но IDOR, race conditions, логические уязвимости в авторизации требуют человека с пониманием контекста вашего приложения.

Сколько стоит аудит безопасности от Vibers? От 5 000 ₽/мес (промо) или 30 000 ₽ за разовый аудит. Включает OWASP-проверку и PR с исправлениями.

Какие стеки чаще всего уязвимы? Node.js + Express (нет встроенной защиты, паттерны из туториалов), Python + Flask без ORM, React SPA с открытым API.


Напишите в Telegram @onoutnoxon — проверим ваш код на уязвимости. Первое ревью за 24 часа.

Читайте также

Источники

  1. CMU, Columbia, Johns Hopkins — "Security of AI-Generated Code" (2025)
  2. OWASP Foundation — "OWASP Top 10: 2021" (актуальная версия)
  3. Snyk — "State of Open Source Security Report 2025"
  4. Vibers / habab.ru — данные из практики ревью вайбкодинг-проектов (2025–2026)

О сервисе "Vibers — Код-ревью для вайбкодинг-проектов"

Сервис код-ревью с участием человека для команд, использующих дешёвых AI-разработчиков. Проверяем коммиты по вашему ТЗ, исправляем проблемы и отправляем pull request'ы.

Ключевые преимущества:

  • Оставьте дешёвых вайбкодеров ($1-5/час), но добавьте слой качества
  • Получайте PR с реальными исправлениями, а не просто баг-репорты
  • Отслеживание соответствия ТЗ — код соответствует вашим требованиям
  • Ревью безопасности ловит секреты, инъекции, проблемы OWASP
  • Вайбкодеры учатся на наших исправлениях — качество растёт со временем
  • В 10 раз дешевле, чем нанимать сеньора для код-ревью

Для кого подходит:

Основатели стартапов, использующие Upwork/Fiverr разработчиков Нетехнические CEO с вайбкодинг-проектами AI-first команды, использующие Cursor, Copilot, Claude Code Агентства, аутсорсящие дешёвым разработчикам Продакт-менеджеры, которые не читают код, но имеют ТЗ

Сценарии использования:

💡 Ревью AI-сгенерированных PR перед мержем
💡 Проверка, что вывод вайбкодера соответствует Google Doc ТЗ
💡 Аудит безопасности кода от разработчиков за $1-5/час
💡 Поиск галлюцинаций AI в вайбкодинг-фичах
💡 Контроль качества между дешёвой разработкой и продакшном

📰 Промо-статьи наших решений

Изучите детальные обзоры наших технологических решений для различных отраслей:

🚀 Работаю до результата

Работаю до результата и бизнес-ценности, быстро корректирую подходы в процессе. Использую современный стек для качественного и быстрого решения задач.