Руководство · privacy-security
Как не дать ИИ-ассистенту выдавать документы, которые человеку недоступны
Индекс собирал сервисный аккаунт, которому было видно всё, поэтому ассистент способен процитировать что угодно. Ничего не падает, никого не оповещают, а утечку находят, когда кто-то читает ответ, не предназначенный ему.
Сбой, который не порождает ошибки
Внутреннего ассистента обычно строят одинаково: натравить обходчик на вики, диск, систему тикетов и репозитории, векторизовать всё найденное и поставить перед этим окно чата. Обходчик работает под сервисным аккаунтом с широкими правами на чтение, потому что иначе до всех источников не добраться без недели возни с доступами. Это единственное удобство и определяет уровень защищённости всей системы.
Опасность в том, что о себе такой сбой не объявляет. Ни один запрос не падает, ни один алерт не срабатывает, ассистент отвечает бегло и по делу. Проблема всплывает, когда кто-то читает ответ с зарплатными вилками, необъявленной реорганизацией или юридическим спором и понимает, что это не для него, — а к этому моменту тот же ответ, скорее всего, уже получили и другие, которые промолчали.
Почему индекс забывает, кому что было видно
Права живут на документах. У эмбеддингов документов нет — есть векторы, а вектор это позиция в пространстве, где из всех отношений уцелела только близость. Когда контент режут на фрагменты и векторизуют, всё, что исходная система знала о владельце, шаринге и членстве в группах, выбрасывается, если вы намеренно это не перенесли.
Поэтому шаг поиска отвечает на вопрос «какие пассажи ближе всего к запросу», а у близости нет мнения о том, имел ли спрашивающий право их читать. Дальше модель делает ровно то, для чего создана: пишет хороший ответ по переданному ей материалу.
Переносите метки доступа в индекс
Починка начинается на индексации. Каждый фрагмент нужно сохранять вместе с метаданными доступа исходного документа — группы, роли, идентификатор арендатора или идентификатор документа, управляющие оригиналом, — как фильтруемые поля рядом с вектором. Если ваше векторное хранилище не умеет эффективно фильтровать по метаданным, это повод сменить хранилище, а не повод отказаться от контроля.
Прикрепляйте и классификацию, если она есть. Уровень, помечающий запись как данные ограниченного доступа, позволяет применять правила, которые иначе не применимы: вовсе не пускать самое чувствительное в индекс или разрешать его находить, но никогда не отправлять во внешнюю модель.
Фильтруйте на запросе, а не после ранжирования
Запрос должен нести личность спрашивающего, а фильтр применяться до ранжирования. Фильтровать потом — распространённое упрощение, и оно неверно дважды: информация утекает через количество найденного и через время ответа, а результат молча усыхает, так что пользователь с узкими правами получает не лучшие доступные ему фрагменты, а меньше и хуже. В итоге качество ответов падает именно у тех, кто вероятнее всего на это пожалуется.
Не давайте меткам протухать
Индекс — это копия, а права меняются постоянно: доступ отозвали, роль сменили, человек уволился. Переиндексировать на каждое изменение прав непрактично, поэтому работающие системы перепроверяют права в исходной системе в момент ответа, но только для тех нескольких документов, которые реально используются. Это по карману именно потому, что их единицы, и так закрывается окно между отзывом доступа и следующим обходом.
Мультиарендным продуктам нужна более жёсткая линия
Если вы встраиваете это в продукт, а не строите для одной компании, ошибка фильтра пересекает границу клиента, а не внутреннюю. Раздельные индексы или жёсткое разделение по арендаторам стоят дополнительной эксплуатационной тяжести: один пропущенный фильтр в общем индексе — это раскрытие данных между клиентами, а вскрывший его запрос может быть совершенно невинным.
Тестируйте это как систему прав, а не как поиск
Заведите небольшой набор пробных учёток с намеренно разным доступом и фиксированный список вопросов, ответы на которые зависят от документов, доступных лишь части из них. Прогоняйте его на каждое изменение конфигурации поиска и относитесь к утёкшему пассажу как к упавшему тесту, а не как к вопросу качества.
Логируйте и идентификаторы документов, стоящих за каждым ответом. Именно логи поиска позволяют потом установить, кому что было показано, — а если восстановить это по логам нельзя, вы не сможете очертить границы инцидента и вынуждены будете исходить из максимально широкой утечки.