Функция, отвечающая на вопросы по документам, может находить релевантный текст и передавать его модели ИИ. Однако этот текст не всегда безвреден: документ, веб-страница или загруженный пользователем файл могут содержать фразы, пытающиеся изменить задачу, получить постороннюю информацию или инициировать действие. Этот риск называют prompt injection в документах, или косвенной инъекцией, поскольку инструкции поступают из обрабатываемого содержимого и не обязательно из вопроса пользователя.
Для снижения риска недостаточно подобрать идеальную фразу для системного сообщения. Нужно спроектировать приложение так, чтобы полученное содержимое не могло менять разрешения, политики и бизнес-решения, а ответ модели никогда не был достаточным основанием для выполнения действия.
Какой риск необходимо контролировать

Документ может содержать явные инструкции, например «игнорируй предыдущие инструкции», или более завуалированный текст, например просьбу раскрыть внутренние данные. Он также может включать скрытые инструкции в содержимом, извлечённом из HTML, комментариев, метаданных или текста, полученного с помощью OCR. Если этот материал без разграничения смешать с инструкциями приложения, модель может последовать части этих указаний, предвзято изложить их в пересказе или сформировать ответ за пределами предусмотренного сценария.
Риск зависит от возможностей функции. Помощник, который только готовит ответ для проверки, может нанести иной ущерб, чем помощник, способный просматривать учётные записи, оформлять возвраты или отправлять сообщения. Прежде чем предоставлять функцию пользователям, необходимо определить, какую информацию она может получать, какие ответы формировать и какие последствия могут за ними последовать.
Сама по себе prompt injection не доказывает, что средства контроля доступа приложения были обойдены. Однако она может привести к раскрытию информации, ошибочно включённой в контекст, или побудить модель запросить выполнение операции. Защита должна охватывать входные данные, доступные модели данные и последующие действия.
Разделяйте данные, политики и разрешения
Полученное содержимое должно служить источником данных для ответа, а не источником полномочий. Документ может описывать корпоративную политику, но приложение должно отдельно определять, разрешено ли пользователю просматривать этот документ или выполнять связанную с ним операцию. Это решение нельзя делегировать ни тексту, ни сгенерированному ответу.
- Авторизация до получения документов: применяйте контроль доступа при поиске и отбирайте документы с учётом личности пользователя и действующих у него разрешений.
- Минимальный контекст: передавайте только фрагменты, необходимые для задачи. Не включайте данные других учётных записей, секреты, учётные данные и информацию, которая не нужна модели.
- Политики вне модели: вычисляйте разрешения, ограничения и условия бизнес-логики в коде приложения или авторизованных сервисах.
- Ответ как предложение: рассматривайте вывод модели как содержимое, которое нужно проверить, а не как исполняемую инструкцию.
Системная инструкция может помочь обозначить ожидаемое поведение, например указать, что найденный текст является справочным материалом. Но это не граница безопасности: такая инструкция не гарантирует, что модель проигнорирует вредоносные указания, и не заменяет контроль доступа, проверку данных и технические ограничения.
Проектируйте PHP-процесс с явными границами
В PHP целесообразно разделить этапы авторизации, поиска, формирования контекста, вызова модели и проверки результата. Такое разделение упрощает тестирование каждой границы и не позволяет напрямую связать результат работы ИИ с чувствительной операцией.
Следующий фрагмент — иллюстративный псевдокод, а не исполняемый вызов конкретного клиента. Способ формирования запроса и принимаемые поля зависят от используемых API и SDK:
$user = $auth->currentUser();
$documents = $repository->searchAuthorized($user, $question);
$snippets = $contextBuilder->selectRelevant($documents, $maxItems);
// Псевдокод: адаптируйте запрос к конкретному API.
$response = $aiClient->answer([
'task' => 'Ответь, используя справочный материал; не разрешай выполнение действий.',
'untrusted_context' => $snippets,
'question' => $question,
]);
$answer = $responseValidator->validate($response);
return $answer;
Названия в примере приведены для иллюстрации. Пометка контекста как недоверенного помогает обозначить его роль, но не обеспечивает надёжной изоляции: ни формат, ни инструкции сами по себе не мешают модели следовать встроенным указаниям. Фактическое разделение зависит также от передаваемых данных, разрешений, применяемых вне модели, и доступных ей возможностей.
Перед добавлением извлечённого содержимого ограничивайте и нормализуйте его: задавайте максимальный размер, удаляйте ненужные форматы и осторожно обрабатывайте текст, полученный с помощью OCR или с внешних страниц. Не объединяйте документы без ограничений и не включайте по умолчанию всю историю разговора. Если необходимо объяснить ответ или провести аудит, сохраняйте ссылку на источник каждого фрагмента, не записывая в журналы его чувствительное содержимое.
Снижайте последствия манипулирования ответом
Ограничьте доступные модели инструменты теми, которые нужны для конкретной функции. Если задача — только отвечать на вопросы, не предоставляйте ей инструменты для записи или общий доступ к внутренним сервисам. Если требуется запрашивать данные, предоставьте ограниченную операцию, которая применяет авторизацию для каждого запроса, вместо широких полномочий или произвольного доступа к базе данных.
Если модель предлагает выполнить действие, приложение должно проверить это предложение в отдельном процессе. В момент выполнения проверьте личность пользователя, разрешения, параметры, бизнес-правила и актуальное состояние ресурса. Для действий с серьёзными последствиями запрашивайте явное подтверждение или проверку человеком. Текстовый ответ модели, даже если он выглядит безопасным или ссылается на документ, не заменяет такую авторизацию.
Проверяйте результат и перед показом или обработкой: сверяйте ожидаемый формат, ограничивайте длину и отклоняйте поля или значения, выходящие за допустимые пределы. Если ожидается определённая структура, разбирайте её и проверяйте поля по детерминированным правилам. Экранирование вывода и защита от инъекций в HTML, SQL и команды по-прежнему необходимы: генерация с помощью ИИ не делает полученный текст доверенным.
Тестируйте атаки и ожидаемое поведение
Тесты должны охватывать весь процесс, а не только проверять, правильно ли модель отвечает на системную инструкцию. Подготовьте обычные и атакующие документы, которые пытаются изменить задачу, запросить неразрешённые данные или побудить к действию. Учитывайте разные исходные форматы, например текст, извлечённый из HTML, длинные документы и содержимое, где инструкции смешаны с легитимной информацией.
- Проверьте, что поиск никогда не возвращает документы, недоступные пользователю по его разрешениям, даже если вопрос прямо запрашивает эти данные.
- Убедитесь, что атакующие документы не включают инструменты и не меняют бизнес-правила.
- Подтвердите, что некорректный или неожиданный ответ отклоняется, а для чувствительной операции требуется отдельная авторизация.
- Оцените полезность и корректность ответов по обычным документам, чтобы выявить неприемлемое ухудшение функции из-за ограничений.
- Повторяйте тесты при смене модели, шаблона инструкций, механизма поиска, инструментов или процесса извлечения данных.
Задайте измеримые критерии приёмки: какие данные никогда не должны появляться, какие действия должны оставаться заблокированными и как система должна отвечать при недостатке подтверждающих данных. Отдельный тест не гарантирует безопасность, но повторяемый набор тестов помогает обнаруживать регрессии и сравнивать изменения конфигурации.
Записывайте сигналы, не накапливая чувствительные данные
Для расследования сбоев записывайте идентификаторы запросов, версию конфигурации, внутренние идентификаторы или ссылки на использованные документы, решения об авторизации, вызванные инструменты и результаты проверок. Записать ссылку не значит сохранить сам документ или его фрагменты. Не храните чувствительные фрагменты, если для этого нет конкретной необходимости и специальных мер контроля доступа, защиты и хранения.
Добавьте метрики отклонений, ошибок формата и сбоев поставщика, чтобы отличать проблемы безопасности от операционных проблем. Не сохраняйте автоматически полные промпты, документы и ответы, если они содержат персональные данные, коммерческую тайну или регулируемую информацию. Определите сроки хранения, правила доступа и маскирования чувствительных данных; когда этого достаточно, записывайте хеши, идентификаторы и структурированные события. Не допускайте, чтобы журналы стали новым каналом раскрытия содержимого, которое функция должна была защищать.
Контрольный список перед включением функции

- Проверяются ли разрешения перед получением каждого документа?
- Является ли передаваемый контекст минимальным и ограниченным и обрабатывается ли он как недоверенный ввод?
- Применяются ли политики и бизнес-правила вне модели?
- Ограничены ли инструменты и проверяется ли авторизация повторно для каждой операции?
- Проверяются ли ответы до показа пользователю или преобразования в действия?
- Предусмотрены ли проверка человеком или подтверждение для решений с серьёзными последствиями?
- Есть ли повторяемые тесты на атаки и журналы с контролируемыми сроками хранения?
Если на какой-либо вопрос ответ отрицательный, ограничьте область применения функции или оставьте действия в режиме предложений, пока проблема не будет устранена. Защита от prompt injection в документах не зависит от того, всегда ли модель правильно интерпретирует содержимое: она зависит от того, продолжают ли действовать ограничения доступа и операций даже в случае ошибки модели.



