Логотип ConstructiCat
CodeBust.
Навигация по разделу ▾

Слепая зона безопасности.

ИИ-ассистенты выдают функциональный код, который молча опускает средства защиты, которые человек добавил бы по привычке — валидацию ввода, авторизацию, кодирование вывода, работу с секретами — потому что "оно компилируется и возвращает 200" выглядит как готово.

##Признаки и симптомы

Ревьюер замечает слепую зону безопасности, когда код работает на счастливом пути, но средства защиты, которые человек с настроем на безопасность добавляет рефлекторно, попросту отсутствуют. Модель демонстрирует функцию, а не защиту. Характерные признаки:

  • Запросы / команды, собранные конкатенацией строк вместо параметризованных (точки внедрения SQL/команд/LDAP).
  • Пользовательский ввод попадает в вывод без кодирования (отражённый/хранимый XSS) или в fs/child_process/fetch без белого списка (обход пути, SSRF).
  • Эндпоинт аутентифицирует, но никогда не авторизует — он проверяет, кто вы, но никогда — можете ли вы трогать эту запись (IDOR / нарушенная авторизация на уровне объектов).
  • Захардкоженные секреты — ключи API, токены, пароли БД встроены "чтобы оно запустилось".
  • Средства защиты, отсутствующие по упущению: нет CSRF-токена, нет заголовков безопасности, нет ограничения частоты, слабая/устаревшая криптография (MD5, SHA-1, Math.random() для токенов).
  • Театр комментариев: на месте реальной проверки стоит комментарий // validate input или // TODO: add auth. OX Security обнаружил избыточные построчные комментарии («Comments Everywhere») в 90–100% изученного кода, сгенерированного ИИ; при этом запахе такой комментарий часто заменяет собой отсутствующую логику.
// Сгенерированный ИИ обработчик Express — выглядит завершённым, выпускает четыре дыры
app.get("/api/orders/:id", authMiddleware, async (req, res) => {
  const apiKey = "sk_live_8f3b2a91c7d44e0f";            // 1. захардкоженный секрет
  const { rows: [order] } = await db.query(
    `SELECT * FROM orders WHERE id = ${req.params.id}`   // 2. SQL-инъекция
  );
  res.send(`<h1>Order for ${order.customerName}</h1>`);  // 3. отражённый XSS
  // 4. IDOR: authMiddleware подтверждает вход, но никогда не проверяет order.userId === req.user.id
});

Четыре различные уязвимости, ноль падающих тестов — запах в том, чего нет.

##Причины проблемы

Почему модели это порождают

  • Цель обучения — правдоподобие, а не безопасность. Предсказание следующего токена оптимизирует под самый распространённый способ писать код, а публичные корпуса переполнены учебными сниппетами со склейкой SQL-запросов из строк и без авторизации. В статье OX Security о безопасности вайб-кодинга это сказано прямо: «Конкатенация строк чаще всего встречается в обучающих данных». В бенчмарке SusVibes Университета Карнеги — Меллона на 200 реальных задачах по разработке функциональности SWE-Agent с Claude 4 Sonnet выдавал функционально корректное решение примерно в 61% случаев, а безопасное — лишь примерно в 10,5%.
  • «Готово» определяется счастливым путём. LLM оптимизирует под то, чтобы видимый запрос выполнился успешно. Средства защиты не дают никакого положительного сигнала при быстром прогоне — отсутствующая проверка не роняет ни одного теста и не ломает демо, — поэтому они выпадают.
  • Нет контекста репозитория. Модель не видит вашу вспомогательную функцию authorize(), вашу схему валидации или ваш менеджер секретов, поэтому встраивает литеральный ключ или пропускает проверку вместо переиспользования существующего средства защиты.
  • Угодливость + скорость. Модель возвращает ровно то, что вы попросили («добавь эндпоинт заказа»), а не модель угроз вокруг него, а узкие места вроде ревью и моделирования угроз — именно то, что устраняет разработка на скорости ИИ. Главный вывод OX Security: в сгенерированном ИИ коде не больше уязвимостей на строку, чем в написанном человеком; уязвимый код в продакшен отправляет скорость, потому что «полноценное ревью кода просто не может масштабироваться под новую скорость выдачи». OX также предупреждает о приложениях, «небезопасных по глупости» (insecure by dumbness): их собирают с помощью ИИ и выкатывают нетехнические пользователи, у которых нет экспертизы в безопасности, чтобы заметить, чего не хватает.
  • Устаревание из-за порога обучения. Модели хватаются за криптографические и библиотечные паттерны, которые были приемлемы годы назад (MD5, SHA-1, устаревшие опции TLS, старые потоки аутентификации).

Почему это вредит

  • Прямая эксплуатируемость. Отчёт Veracode 2025 GenAI Code Security Report (80 задач, более 100 LLM) зафиксировал уязвимости в 45% случаев, а защититься от межсайтового скриптинга (CWE-80) модели не смогли в 86% случаев. CodeRabbit обнаружил XSS-уязвимости в пул-реквестах, написанных при участии ИИ, в 2,74 раза чаще, чем в написанных только людьми; Tenzai выяснил, что ни одно из 15 приложений, собранных пятью агентами, не имело защиты от CSRF и не выставляло заголовки безопасности; Escape.tech нашёл более 400 раскрытых секретов в более чем 5600 приложениях, написанных вайб-кодингом.
  • Невидимо для тестов и для читателей. Отсутствующая проверка авторизации не имеет падающего теста и диффа, на который можно указать, поэтому она беспрепятственно проходит ревью — а объём вывода ИИ означает, что ревью не масштабируется, чтобы её поймать.
  • Нарастающий техдолг. Анализ GitClear 2025 года, охвативший 211 млн изменённых строк, показал, что доля строк, связанных с рефакторингом («перемещённых»), упала с 25% изменённых строк в 2021 году до менее чем 10% в 2024-м, тогда как доля скопированных строк выросла с 8,3% до 12,3% и в 2024 году впервые превысила долю перемещённых; число блоков из пяти и более дублирующихся строк за 2024 год выросло примерно в восемь раз. Один и тот же небезопасный шаблон клонируется по всей кодовой базе и умножает радиус поражения каждой слепой зоны.

##Лечение

Тактики ревью и промптинга

  • Назовите модель угроз в промпте. "Напиши этот эндпоинт, считая, что id контролируется злоумышленником; обеспечь авторизацию на уровне объектов, параметризуй все запросы, кодируй весь вывод и читай секреты из process.env". Указание противника переворачивает поведение по умолчанию.
  • Принуждайте к переиспользованию существующих средств защиты. "Используй нашу вспомогательную функцию authorize(user, 'order', id) и валидатор orderSchema — не пиши новую валидацию". Это прямо противодействует причине отсутствия контекста репозитория (и смежному запаху Дублирование кода).
  • Заставьте модель запускать инструменты. Требуйте, чтобы она запускала semgrep --config p/owasp-top-ten, gitleaks detect, npm audit и ваш конфиг eslint-plugin-security, затем исправляла то, что они отметят, прежде чем объявлять о готовности.
  • Явно спрашивайте об отрицательных моментах. "Перечисли вопросы аутентификации, авторизации, валидации ввода, кодирования вывода и работы с секретами для этого обработчика и покажи, где каждый из них обеспечен". Пробел в этом списке и есть ошибка.
  • Моделируйте угрозы для диффа, а не для строки. Опасные дыры — это упущения, поэтому проводите ревью, спрашивая "какое средство защиты должно быть здесь и которого нет?", а не выискивая плохие строки.

Рефакторинг — параметризуйте запрос (убивает инъекцию), кодируйте вывод (убивает XSS), добавьте проверку авторизации на уровне объекта (убивает IDOR) и перенесите встроенный секрет в конфигурацию:

// ПОСЛЕ
app.get("/api/orders/:id",
  authMiddleware,
  validate(orderParamsSchema),                    // валидация ввода
  async (req, res) => {
    const { rows: [order] } = await db.query(
      "SELECT * FROM orders WHERE id = $1", [req.params.id]   // параметризовано
    );
    if (!order || order.userId !== req.user.id) {            // авторизация на уровне объектов
      return res.sendStatus(404);
    }
    res.json({ customerName: order.customerName });          // структурированный вывод, автоматически кодируется
  }
);
// секрет: process.env.STRIPE_API_KEY, загружается один раз при старте, никогда не встраивается

Там, где запах распространился клонированием, исправьте его один раз и примените к средству защиты (requireOrderOwnership, escapeHtml) Извлечение метода, чтобы все места вызова пользовались одной проверенной реализацией вместо N копий.

##Обнаружение анализаторами