Аудит безопасности AI-кода: 7 уязвимостей, которые регулярно создают языковые модели
Обучающие выборки больших языковых моделей состоят из миллионов открытых репозиториев и учебных туториалов. В туториалах почти всегда опускают проверки прав доступа, пессимистичные блокировки строк БД и верификацию криптографических подписей вебхуков ради краткости примера. В результате агент генерирует код, который идеально проходит позитивные юнит-тесты, но оказывается беззащитным в боевой эксплуатации.
1. Синдром «счастливого пути» (Happy Path Bias)
По умолчанию ИИ-ассистент решает функциональную задачу: «сделай эндпоинт списания бонусов» или «добавь скачивание счёта по ID». Если инженер явно не поставил задачу моделирования угроз (STRIDE / OWASP API Security Top 10), модель предполагает, что клиент передаёт честные параметры и никогда не отправляет 20 параллельных запросов в одну миллисекунду.
2. Семь уязвимостей, которые мы находим на каждом аудите
- TOCTOU и состояние гонки (Race Condition) на балансах: чтение баланса обычным
SELECT, проверкаif user.balance >= priceв Python и последующийUPDATEбез блокировки строки. - BOLA / IDOR в API: выборка сущности по первичному ключу
get_by_id(order_id)без проверки того, что заказ принадлежит текущему авторизованному пользователю. - Отсутствие идемпотентности платёжных вебхуков: повторное начисление подписки при ретрае уведомления от платёжного шлюза.
- DOM-based XSS на фронтенде: вставка пользовательского ввода в уведомления через
innerHTMLвместо безопасногоtextContent. - Инъекции через конфигурационные шаблоны: подстановка неэкранированных переменных запроса в скрипты или серверные директивы.
- SSRF при загрузке внешних URL: отсутствие фильтрации приватных диапазонов IPv4/IPv6 (
127.0.0.0/8,169.254.169.254) при превью ссылок. - Утечка чувствительных данных в структурные логи: логирование всего словаря
request.headersили.envпри необработанном исключении.
SELECT ... FOR UPDATE + UNIQUE индекс идемпотентности), а не только на проверки в коде приложения.
3. Как правильно защитить транзакцию от двойного списания
Сравните безопасный паттерн атомарного списания в PostgreSQL + SQLAlchemy 2.0, который мы требуем на защите проектов в VibeCoder School:
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с пользовательскими строками.