Аудит безопасности AI-кода: 7 уязвимостей, которые регулярно создают языковые модели

Обучающие выборки больших языковых моделей состоят из миллионов открытых репозиториев и учебных туториалов. В туториалах почти всегда опускают проверки прав доступа, пессимистичные блокировки строк БД и верификацию криптографических подписей вебхуков ради краткости примера. В результате агент генерирует код, который идеально проходит позитивные юнит-тесты, но оказывается беззащитным в боевой эксплуатации.

1. Синдром «счастливого пути» (Happy Path Bias)

По умолчанию ИИ-ассистент решает функциональную задачу: «сделай эндпоинт списания бонусов» или «добавь скачивание счёта по ID». Если инженер явно не поставил задачу моделирования угроз (STRIDE / OWASP API Security Top 10), модель предполагает, что клиент передаёт честные параметры и никогда не отправляет 20 параллельных запросов в одну миллисекунду.

2. Семь уязвимостей, которые мы находим на каждом аудите

  1. TOCTOU и состояние гонки (Race Condition) на балансах: чтение баланса обычным SELECT, проверка if user.balance >= price в Python и последующий UPDATE без блокировки строки.
  2. BOLA / IDOR в API: выборка сущности по первичному ключу get_by_id(order_id) без проверки того, что заказ принадлежит текущему авторизованному пользователю.
  3. Отсутствие идемпотентности платёжных вебхуков: повторное начисление подписки при ретрае уведомления от платёжного шлюза.
  4. DOM-based XSS на фронтенде: вставка пользовательского ввода в уведомления через innerHTML вместо безопасного textContent.
  5. Инъекции через конфигурационные шаблоны: подстановка неэкранированных переменных запроса в скрипты или серверные директивы.
  6. SSRF при загрузке внешних URL: отсутствие фильтрации приватных диапазонов IPv4/IPv6 (127.0.0.0/8, 169.254.169.254) при превью ссылок.
  7. Утечка чувствительных данных в структурные логи: логирование всего словаря request.headers или .env при необработанном исключении.
Золотое правило AppSec для AI-кода: любая финансовая операция или смена статуса заказа должна опираться на атомарные ограничения уровня базы данных (SELECT ... FOR UPDATE + UNIQUE индекс идемпотентности), а не только на проверки в коде приложения.

3. Как правильно защитить транзакцию от двойного списания

Сравните безопасный паттерн атомарного списания в PostgreSQL + SQLAlchemy 2.0, который мы требуем на защите проектов в VibeCoder School:

src/infrastructure/database/dao/wallet_dao.py
from decimal import Decimal
from uuid import UUID
from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession
from src.infrastructure.database.models import WalletModel

class WalletDAO:
    def __init__(self, session: AsyncSession) -> None:
        self._session = session

    async def atomic_debit(self, user_id: UUID, amount: Decimal) -> bool:
        if amount <= Decimal("0"):
            raise ValueError("Сумма списания должна быть строго положительной")

        stmt = (
            update(WalletModel)
            .where(
                WalletModel.user_id == user_id,
                WalletModel.balance >= amount,
            )
            .values(balance=WalletModel.balance - amount)
            .returning(WalletModel.balance)
        )
        result = await self._session.execute(stmt)
        return result.scalar_one_or_none() is not None

4. Обязательный чек-лист перед мержем AI-диффа

  • Все роутеры проверяют связку (entity_id, current_user.id) на уровне SQL-запроса;
  • Внешние вебхуки проверяют HMAC-подпись в константное время (hmac.compare_digest);
  • На фронтенде включён строгий заголовок Content-Security-Policy и отсутствуют вызовы innerHTML с пользовательскими строками.

Читайте также в инженерном блоге