ESPNAre the Longhorns laying too many points in Knoxville?RTP Desporto"Ruído impede que arbitragem se abra para fora" - Fontelas GomesThe Jerusalem PostFirst day of United Nations General Assembly highlights criticism of Israel's regional activityDaily MaverickFEMINIST HISTORY: Pacifist Emily Hobhouse’s 1926 state funeral to be brought back to life in BloemfonteinInquirerPH may achieve full electrification only by 2033 – lawmakerIl Fatto QuotidianoLa Russia respinge la proposta di negoziati di pace di Zelensky. Trump apre alla produzione dei missili Patriot in Ucraina: “Possibile”Digital SpyBBC unveils first look at coastal town-set drama centred on an 'unlikely duo caught up in a crime'VanguardMLS club sacks coach after sexist remark to female refereeStraits Times SportLA28 unveils Venice Beach triathlon courses for 2028 OlympicsKhaosod EnglishAmerican Fair coming to Korat for US 250th anniversaryReality BlurredDancing with the Stars season 35 recap: holes start to showEgypt IndependentTemperatures across Egypt to drop following humidity as Autumn begins
The Daily Newsstand · Free, Always
Wednesday, September 23, 2026

RAG с правами доступа: как не показать сотруднику документ, которого он не должен видеть

Translate

Практический разбор решения на примере реального корпоративного FAQ-бота

Начальник смены на складе открывает корпоративного ИИ-ассистента и пишет в чате: «Что делать, если водитель не успел с доставкой?» Через несколько секунд появляется ответ — чёткий, правильный, со ссылкой на источник: регламент логистических операций. Его можно скачать.

Теперь представим, что тот же сотрудник задаёт другой вопрос: «Сколько мы платим перевозчикам за километр?» Ввести такой вопрос ему ничто не мешает. Важно лишь то, что произойдёт дальше. Если файл с тарифной сетке лежит в той же базе данных, что и регламент, ассистент ответит вежливо, точно и приложит ссылку на скачивание.

В этом-то и проблема. Семантический поиск мы решили и добились хороших ответов. Но следующая сложная задача — сделать так, чтобы ассистент отвечал только на основе того, что конкретному человеку разрешено знать.

Кратко: что такое RAG

Большие языковые модели много знают о мире и ничего — о вашей компании. Они никогда не читали ваш онбординг, шаблоны договоров или отчёты об инцидентах за прошлый квартал. Retrieval-Augmented Generation (RAG), то есть генерация с дополнением через семантический поиск, закрывает этот пробел. Термин появился в статье Патрика Льюиса и коллег из Facebook AI Research 2020 года, и идея в нём простая. Прежде чем модель ответит, система находит (через векторный поиск) самые релевантные фрагменты в ваших собственных документах и передаёт их модели в качестве контекста. Затем модель генерирует ответ, опираясь на эти фрагменты, и может указать, откуда взята информация.

Под капотом документы нарезаются на фрагменты (chunks, чанки). Каждый чанк превращается в эмбеддинг — набор чисел, вектор, отражающий его смысл, — и сохраняется в векторной базе данных. Когда приходит вопрос, его переводят в эмбеддинг тем же способом, а база возвращает чанки, чьи векторы ближе всего к нему. Поэтому запрос «водитель опоздал» находит абзац под заголовком «Обработка прибытий не вовремя», хотя общих слов у них нет.

Подход распространился быстро. Morgan Stanley выдал своим финансовым консультантам похожего ассистента, работающего поверх примерно 100 000 внутренних аналитических отчётов и документов, и, по словам компании, им пользуются более 98% команд консультантов. Тот же подход можно найти почти везде, где документов больше, чем люди способны запомнить:

  • Логистика и транспорт

  • Юридические фирмы

  • Онлайн-школы и продавцы курсов

  • Медицина, страхование, банки, HR-отделы, IT-поддержка: везде, где люди снова и снова задают одни и те же вопросы к массе PDF-файлов.

Но не всем положено видеть всё

У каждой из этих организаций есть иерархия доступа. Помощник юриста не должен листать дела клиентов другой команды. Сотруднику поддержки онлайн-школы нужны правила возврата, но не таблица партнёрских комиссий. В отделе безопасности сотрудник должен знать инструкции по своим объектам, и ему незачем читать отчёт об уязвимостях других объектов и тем более клиентов.

Причём границы не всегда совпадают с границами документов. Справочник сотрудника может быть открыт для всех, кроме одной главы — о дисциплинарных процедурах и зарплатных вилках, которую должны читать только руководители и HR. Один файл — две аудитории.

Без контроля доступа RAG-система всё это стирает. Она становится самым эффективным инструментом утечки данных из всех, что компания когда-либо внедряла: отвечает простым языком, но и прикладывает ссылки на источники.

Это не гипотеза. Внедрения Microsoft Copilot столкнулись именно с этой проблемой, которую назвали oversharing — избыточным доступом. Ассистент соблюдал существующие права, но из-за многолетней небрежной раздачи доступов в SharePoint данные о зарплатах, HR-файлы и стратегические документы стали находиться одним запросом. Вендоры в сфере безопасности формулируют прямо: ИИ не создал новых доступов, он сделал существующие плохие доступы тривиально обнаружимыми. OWASP теперь включает недостаточный контроль доступа к векторным хранилищам в свой Top 10 для LLM-приложений (LLM08: Vector and Embedding Weaknesses).

Хорошая новость: это всё ещё обычная сегрегация данных

RAG может казаться системой нового типа, но в основе у неё — запрос к базе данных. «Найди пять чанков, ближайших к этому вектору» — это SELECT с необычным ORDER BY. А значит, старые правила разграничения данных по-прежнему действуют.

Главное правило — фильтровать до того, как модель что-либо увидит. Системный промпт «не раскрывай конфиденциальную информацию» — это не контроль доступа. Языковую модель можно "уговорить" нарушить инструкции. Как только запрещённый абзац попал в контекстное окно, уже поздно. Безопасен только тот документ, который вообще не был извлечён.

С учётом этого правила есть четыре распространённых способа разграничить данные:

  1. Физическая изоляция: отдельная база данных или отдельное развёртывание на каждого клиента или зону безопасности. Самая прочная граница и самая дорогая. Подходит для регулируемых отраслей и разных клиентов.

  2. Логические разделы: одна база, но отдельная коллекция, индекс или пространство имён на каждую роль или группу. Каждый запрос идёт ровно в один раздел, остальные из этого запроса недостижимы.

  3. Фильтрация по метаданным в общем индексе: каждый чанк несёт метки вроде allowed_groups: ["hr", "managers"], и каждый поиск включает фильтр по группам пользователя. Гибко и детально. Слабое место — одного пропущенного фильтра в одной ветке кода достаточно, чтобы утекло всё. Хорошие разборы есть у Pinecone и Oso.

  4. Авторизация в момент запроса: сначала извлекаются кандидаты, затем каждый проверяется по правам в исходной системе (SharePoint, Google Drive, сервис авторизации вроде OpenFGA), и только потом передаётся дальше. Права всегда актуальны, но это медленнее и сложнее в реализации на больших объёмах.

Реальные системы часто сочетают несколько подходов. Наш FAQ-бот использует второй.

Наш подход: одна папка на роль

В нашем проекте — бэкенд на FastAPI с агентом на LangGraph и PostgreSQL/pgvector — правило такое: роль — это папка, а папка — это коллекция.

Пример:

documents/

├── faq/ → общая база знаний для всех ├── support/ → служба поддержки: регламенты, эскалация, правила возврата └── management/ → руководители: всё вышеперечисленное + зарплатные вилки, дисциплинарная глава.

Мэппинг в конфигурации связывает роли с этими коллекциями ({"administrator": "faq", "support": "support", ...}). Когда администратор вручную запускает индексацию (разбивки на чанки и векторизацию) или это происходит автоматически, система обходит каждую папку и записывает эмбеддинги её файлов в собственную коллекцию pgvector этой папки. Документ из support/ никогда не попадёт в faq/.

Это же решает проблему со справочником сотрудника. Заказчик держит две версии: полную — в management/, и версию без чувствительной главы — в общих папках. Редактирование происходит там, где люди его и так понимают, — в самих документах, а не в коде.

Почему папки хорошо работают

  • Понятные границы. Любой может открыть дерево каталогов и увидеть, кто что читает. Никому не нужно разбираться в комбинациях меток или файлах политик.

  • Привычный интерфейс для заказчика. Владельцы бизнеса и так умеют работать с файлами и папками. Решить, что видит роль, — значит перетащить файл в папку. Та же структура ложится на общий диск вроде Google Drive или SharePoint, так что заказчик может управлять доступом в инструменте, которым уже пользуется.

  • Надёжная изоляция по построению. Поисковик на каждый запрос создаётся ровно для одной коллекции, поэтому запрос не может дотянуться до данных другой роли, даже если модель об этом попросит.

  • Простой аудит. Вопрос «какие документы видит поддержка?» решается командой ls documents/support.

И где они не справляются

  • Дублирование. Документ, нужный трём ролям, лежит в трёх папках и индексируется трижды. Копии расходятся, когда кто-то обновляет только одну из них. Компромисс: больше данных в пользу простоты.

  • Одна роль на пользователя. Сотрудник, который одновременно и «поддержка», и «продажи», в схему вписывается плохо — нужна либо составная роль, либо общая папка.

  • Высоко-уровневое разбиение. Доступ на уровне главы означает ручную подготовку отдельных версий документа.

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

Путь пользователя шаг за шагом

Вот что происходит, когда сотрудник задаёт вопрос:

  1. Вход. Пользователь авторизуется и получает подписанный JWT с его идентификатором и ролью. Заблокированные пользователи отсекаются на этом этапе и при каждом последующем запросе.

  2. Вопрос. Сообщение уходит на бэкенд с токеном в заголовке Authorization.

  3. Определение коллекции. Сервер находит пользователя в базе и сопоставляет его роль с названием коллекции. Роль берётся из собственных записей сервера. Ничто, отправленное клиентом, не может её изменить.

  4. Поиск. Результат работы инструмента агента search_documents возвращается только для этой коллекции. С точки зрения этого запроса документов других ролей не существует.

  5. Ответ. Модель пишет ответ на основе найденных чанков и передаёт его потоком через SSE вместе со ссылками на источники (имя файла и фрагмент текста), которые отображаются в боковой панели.

  6. Приватная история. Переписки хранятся отдельно для каждого пользователя, поэтому никто не откроет чужой чат, угадав его ID.

Проверка доступа происходит на шаге 3. К моменту, когда в дело вступает модель, данные уже сужены до того, что этому пользователю разрешено видеть.

Незаметная утечка: кнопка «Скачать»

Ссылки на источники — одно из лучших свойств RAG. Пользователи доверяют ответам, которые могут проверить, поэтому в нашей панели источников можно кликнуть по имени файла и скачать оригинал.

Но эта кнопка — ещё и лёгкий путь для утечки. Соблазнительно сделать её статической ссылкой вида /files/management/salary-bands.pdf, отдаваемой прямо с диска. Тогда любой пользователь, угадавший этот URL или получивший его от коллеги, скачает файл независимо от роли. Поиск будет надёжно закрыт, а скачивание — открыто всем.

Мы отдельно сфокусировались на эндпоинте скачивания:

  • Только с аутентификацией. GET /documents/{filename} требует тот же JWT, что и чат. Фронтенд запрашивает файл с токеном в заголовке, превращает ответ в blob и вызывает браузерное «Сохранить как». Токен никогда не попадает в URL, откуда он мог бы утечь в логи или историю браузера.

  • Только в пределах папки роли. Сервер заново определяет коллекцию пользователя (ничему из того, что прислал клиент, он не доверяет) и ищет файл только внутри documents/{collection}/.

  • Защита от хаков с путями. Имена файлов экранируются. Всё, что содержит .., разделители каталогов/файлов или абсолютные пути, отклоняется, а итоговый путь должен пройти строгую проверку relative_to(collection_root).

  • Никаких утечек фактов существования. Файл, который лежит в папке другой роли, возвращает 404 — ровно как файл, которого нет вовсе. Ответ 403 подтвердил бы атакующему, что salary-bands.pdf действительно существует.

  • Никаких особых случаев. Даже администратор скачивает только из своей коллекции. Каждое исключение из правила — это место, где что-то может сломаться.

  • Покрыто тестами. Автоматическе юнит-тесты проверяют стандартный сценарий, отказ при доступе к чужой роли, обход путей, запросы без аутентификации и отсутствующие файлы.

Принцип такой: каждый канал, по которому данные покидают систему, нуждается в собственной проверке — ответ, фрагмент в ссылке на источник, скачивание, история чата и любые логи.

Другие способы изоляции

Если папки не подходят вашей организации, рассмотрите такие варианты:

  • ACL в метаданных в той же таблице pgvector: каждый чанк помечается разрешёнными группами, и каждый запрос фильтруется по ним. Хорошо работает, когда документы разделяются между множеством пересекающихся групп.

  • Row-Level Security в PostgreSQL. Поскольку pgvector живёт внутри Postgres, сама база может обеспечивать правило «эта сессия видит только строки своих групп» — даже если код приложения забудет про фильтр.

  • Синхронизация ACL из исходной системы (Google Drive, SharePoint, Confluence) в метаданные чанков, чтобы ИИ-ассистент наследовал права, которые люди и так поддерживают в источниках данных. История с Copilot здесь служит предупреждением: плохие права наследуются тоже, поэтому сначала проверьте их.

  • Авторизация на основе отношений (системы в духе Zanzibar, например OpenFGA или SpiceDB) для сложных графов «кто что может видеть» с проверкой в момент запроса.

Вывод

RAG-ассистент заслуживает доверия ровно настолько, насколько защищён самый слабый путь к данным. Выберите модель разграничения, которую можно объяснить одним предложением. Фильтруйте данные ещё до того, как модель увидит хоть какой-то контекст. А затем повторите ту же проверку для каждого другого канала, по которому данные покидают систему, — особенно для кнопки «Скачать».

Наша версия в одном предложении: ваша роль — это ваша папка, и всё, что за её пределами, для вас не существует. Это не самый гибкий дизайн, зато офис-менеджер заказчика может его понять, проверить и поддерживать, просто перетаскивая файлы между папками.

View the original on Хабр

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.