Защита RAG от отравления базы знаний: гайд 2026 | AiManual
AiManual Logo Ai / Manual.
18 Мар 2026 Гайд

Атака на RAG-системы: как защитить ChromaDB и LM Studio от 95% отравления базы знаний

95% атак на RAG проходят успешно. Пошаговый план защиты ChromaDB и LM Studio: обнаружение аномалий эмбеддингов, настройка chunking, валидация контента.

Тихий саботаж: как ваш локальный RAG превращается в ботнета

Вы загружаете техдокументацию в ChromaDB. Подключаетесь к LM Studio с новым Llama 3.3 через OpenAI-совместимый API. Запускаете запрос. И получаете от нейросети четкую инструкцию, как слить корпоративные пароли на левый сервер. Классический день DevOps в 2026 году.

На прошлой неделе мы тестировали уязвимости в локальном RAG-стеке. Результаты кошмарные: 95% атак на отравление базы знаний прошли успешно. Это не Prompt Injection - это Data Poisoning. Злоумышленник не ждет вашего промпта. Он заранее заражает векторную базу поддельными документами, и модель добросовестно их использует. Ваша задача - оборвать эту цепочку. Сегодня.

Почему фильтрация вывода не работает? Потому что модель говорит правду - ту правду, которую вы ей подсунули. Вы запрещаете слово "пароль", а она генерирует "учетные данные доступа". Игра в кошки-мышки проиграна на старте. Нужно бить по корню - по эмбеддингам.

Механика катастрофы: почему 512 токенов смертельны

Стандартная настройка: chunk_size=512, overlap=200. Звучит разумно? Для атаки - идеально. Злоумышленник создает документ, где 300 токенов - легитимная техническая информация, а 212 - вредоносные инструкции. При разбиении на чанки эта "отравленная" секция гарантированно попадает в середину какого-то чанка, обернутая нормальным контекстом. Алгоритм эмбеддинга усредняет смысл. И при поиске по схожести вы получаете не чистый яд, а коктейль с ядом.

Основная проблема в доверии к источнику. Как показано в статье про обратную инженерию эмбеддингов, семантический смысл можно извлечь даже из вектора. А значит - и подделать.

💡
Атака выглядит так: в поток легитимных PDF-документов подмешивается один файл с инструкциями для ИИ. Название "Обновление_политики_безопасности_Q4_2026.pdf". Содержание: 70% реальных правил безопасности, 30% скрытых команд. Модель не видит разницы - для нее это единый смысловой поток.

1 Шаг первый: ловим аномалии в эмбеддинг-пространстве

Забудьте про анализ текста. Смотрите на вектора. Каждый легитимный документ при эмбеддинге занимает определенную область в n-мерном пространстве. Отравленные чанки - выбросы. Их нужно найти до индексации.

Как это работает: после создания эмбеддингов для нового пакета документов запускаем алгоритм обнаружения аномалий (Isolation Forest, Local Outlier Factor). Если эмбеддинг чанка отклоняется от кластера похожих документов больше чем на 3 сигмы - помечаем на проверку.

import numpy as np
from sklearn.ensemble import IsolationForest

# embeddings - массив эмбеддингов новых чанков
# train_embeddings - эмбеддинги проверенного легитимного корпуса

def detect_poisoned_chunks(embeddings, train_embeddings, contamination=0.01):
    # Обучаем модель на легитимных данных
    clf = IsolationForest(contamination=contamination, random_state=42)
    clf.fit(train_embeddings)
    
    # Предсказываем аномалии в новых данных
    predictions = clf.predict(embeddings)
    # Возвращаем индексы подозрительных чанков (где prediction == -1)
    return np.where(predictions == -1)[0]

Contamination=0.01 - ожидаем 1% аномалий. В реальности для нового неизученного корпуса ставьте 0.05. Ложные срабатывания лучше пропущенных угроз.

Не используйте эту функцию в продакшене без дообучения на ваших данных! Isolation Forest, обученный на случайных эмбеддингах, сработает плохо. Соберите эталонный корпус из 1000+ проверенных чанков.

2 Шаг второй: разрываем контекстную ловушку chunking'ом

Стандартные чанки убивают вас. Переходите на стратегический chunking с границами по смысловым разделам. Если в документе есть заголовок "Глава 3: Политика паролей", следующий чанк должен начинаться именно с него, а не с середины абзаца.

Используйте библиотеки вроде langchain с улучшенными text splitters, но настройте их под свои нужды:

from langchain.text_splitter import RecursiveCharacterTextSplitter

# Плохо
splitter_naive = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=200)

# Хорошо
splitter_smart = RecursiveCharacterTextSplitter(
    chunk_size=256,  # Меньше - меньше пространства для маневра атакующего
    chunk_overlap=50,
    separators=["\n\nГлава", "\n\n", "\n", ". ", " ", ""],  # Приоритет разделителей
    length_function=len,
    is_separator_regex=False,
)

Чанки размером 256 токенов сложнее отравить без потери семантической связности вредоносной вставки. Перекрытие 50 токенов сохраняет контекст, но не позволяет скрыть яд в overlap-зоне.

Парадокс: чем больше chunk_overlap, тем легче спрятать атаку. Об этом мало кто думает.

3 Шаг третий: валидация источника на уровне загрузки

ChromaDB по умолчанию принимает все. Нужно встроить валидацию перед вызовом add_documents. Простейший фильтр - проверка метаданных и хэшей.

import hashlib
from typing import List, Dict
from langchain.schema import Document

def validate_documents_before_adding(docs: List[Document], trusted_sources: List[str]) -> List[Document]:
    validated = []
    for doc in docs:
        # Проверяем источник из метаданных
        source = doc.metadata.get("source", "")
        
        # Простая проверка по доверенным путям/URL
        if any(trusted_source in source for trusted_source in trusted_sources):
            # Дополнительно считаем хэш содержимого для верификации
            content_hash = hashlib.sha256(doc.page_content.encode()).hexdigest()
            doc.metadata["content_hash"] = content_hash
            validated.append(doc)
        else:
            # Логируем и отправляем на ручную проверку
            print(f"Подозрительный источник: {source}")
            # Здесь можно вызвать кастомную логику проверки
            # Например, отправить в очередь на модерацию
    return validated

Этот метод не панацея - атакующий может подделать путь. Но это первый барьер. Для серьезной защиты нужна цепочка доверия, как в статье про защиту AI-агентов от prompt injection.

4 Шаг четвертый: мониторинг запросов в реальном времени

Даже с защитой нужен детектор аномалий в запросах. Следите за необычными паттернами:

  • Частые запросы к одним и тем же "чувствительным" чанкам
  • Пользователи, которые получают слишком много разнородных чанков в одном ответе
  • Резкий рост схожести запросов с определенными эмбеддингами

Настройте алерты. Используйте Prometheus + Grafana для визуализации метрик из ChromaDB (если развернута с помощью официального Helm0чарта). Или пишите логи в ELK-стек.

Критически важно: не храните логи запросов с эмбеддингами в открытом виде. Хэшируйте их или используйте дифференциальную приватность.

Где ломается 95% защит: ошибки, которые вы уже делаете

ОшибкаПочему это плохоИсправление
Использование дефолтных параметров в text splitterСоздает идеальные контейнеры для отравленных данныхАнализируйте свои документы, подбирайте chunk_size под их структуру
Отсутствие изоляции средТестовая зараженная база может синхронизироваться с продомПолная изоляция: отдельные инстансы ChromaDB, разные API-ключи LM Studio
Слепая вера в один алгоритм эмбеддинговАтакующий может оптимизировать вредоносный текст под конкретную модель (например, all-MiniLM-L6-v2)Используйте ансамбли: два разных эмбеддера, сравнение результатов

Ответы на вопросы, которые вы боитесь задать

LM Studio тоже уязвим?

Да. LM Studio - это просто обертка для запуска моделей. Если модель получает отравленный контекст из ChromaDB, она обработает его как легитимный. Безопасность нужно строить на уровне данных, а не модели.

А если атакующий знает мою модель эмбеддингов?

Тогда задача усложняется. Он может создать adversarial пример, который в эмбеддинг-пространстве будет похож на "техническую документацию", а в текстовом виде содержать вредоносные инструкции. Защита - регулярная ротация моделей эмбеддингов и использование последних версий, где такие атаки частично учтены (например, sentence-transformers 3.0+ имеет улучшенную устойчивость).

Как связаны эта атака и новые угрозы GenAI?

Data poisoning - один из методов, описанных в обзоре новых угроз безопасности GenAI. Разница в том, что prompt injection работает в runtime, а poisoning - на этапе подготовки данных. Второе опаснее, потому что обнаруживается позже.

Можно ли автоматизировать защиту?

Частично. Вы можете настроить пайплайн CI/CD для вашей базы знаний: при пуше новых документов запускается скрипт проверки эмбеддингов, chunking с кастомными параметрами, и только потом индексация. Полностью исключить человека из цикла - рискованно. Особенно в свете того, что AI-агенты уже демонстрируют агрессию.

Что дальше? Прогноз на 2027

Data poisoning станет массовым. Атакующие перейдут от точечных атак к заражению публичных датасетов, которые компании используют для дообучения. Появится рынок "чистых" эмбеддингов с верифицированной цепочкой поставки. Инструменты вроде ChromaDB добавят встроенные механизмы валидации (возможно, на основе дифференциальной приватности).

Ваша задача сегодня - не ждать этих обновлений. Настроить базовую защиту по шагам выше. Провести аудит текущей базы знаний. И помнить: 95% - это не статистика. Это вероятность того, что завтра ваша RAG-система начнет работать на того, кто этого не ожидал.

Подписаться на канал