权限感知检索:企业 RAG 的访问控制必须在向量层
有一种故障模式几乎出现在每一个企业 RAG 部署中:一名员工向内部 AI 助手询问薪酬政策相关问题。系统返回了正确、具体的信息——却是从一份该员工本无权查看的 HR 文档中提取的。由于没有人监控检索层,这件事不会立刻让任何人丢掉工作。但那份机密文档已被索引,用户的查询在语义上命中了它,模型忠实地报告了它所找到的内容。
这个错误并不罕见,它是将公共网络 RAG 模式原封不动地应用于私有组织知识却不做架构适配的默认结果。公共网络 RAG 没有访问控制层,因为公共网络内容本身就没有访问限制。而企业数据有——这一约束从根本上改变了整个系统的设计。
打破一切的核心假设
公共网络 RAG 基于一个简单模型构建:索引所有内容,按语义相似度检索,根据所找到的内容生成回答。这之所以有效,是因为检索语料库是同质的(来自开放网络的文本),且不受访问限制——任何人都可以读取任何人检索到的内容。
企业知识打破了这两个前提。一个典型组织拥有 Confluence 文档、Slack 消息历史、Google Drive 文件、CRM 记录、组织架构图、会议纪要和工程 Wiki——每一类都有其自身的权限模型。支持工程师可以查看客户工单,但无法查看薪资等级。初级分析师可以查看公开看板,但无法查看董事会材料。这些数据分散在数十个系统中,访问策略相互交叉且并不一致。
当你将所有这些数据索引到向量存储中并按相似度查询时,你就将这些权限模型合并到了一个统一的检索界面上。若没有额外的控制手段,检索层就会成为权限提升的攻击面:一个访问权限有限的用户可以通过查询触发对其无权直接打开的文档的检索,而模型将把这些文档合成进回答,仿佛它们完全合规。
最直接的修复方案——"在应用代码中过滤结果再展示给用户"——是大多数团队止步的地方。这远远不够。模型已经处理过该文档了。如果应用层只在生成之后才捕获检索结果,损害已经造成。而且应用层过滤器很容易通过提示注入、API 误用或简单的代码漏洞绕过。
真正的修复是在管道的更早阶段——向量层本身——执行访问控制。
为什么 BM25 在内部实体查询上胜过嵌入
在深入探讨安全问题之前,有一个在安全问题之前就会出现的检索质量问题:企业知识包含的查询类 型与公共网络 RAG 的优化目标截然不同。
网络查询往往是概念性的:"退款政策是什么?"或"如何配置 SSL 证书?"这类查询受益于语义嵌入,因为用户的词汇可能与文档的词汇不同,而嵌入模型会将两者压缩到共同的语义空间中。
内部查询则高度依赖实体:"找 EMEA 团队的 Q3 销售管道评审"、"支付服务的值班轮换是什么"、"查一下 Sarah Kim 上季度的项目分配情况"。这些本质上是对专有名词、标识符和精确短语的查找,而在公共互联网文本上训练的嵌入模型对此处理能力很差。内部术语、产品代码、团队名称和组织专属缩写在公共训练数据中统计上极为罕见,在嵌入空间中代表性不足。
对于这类查询,BM25(最佳匹配 25)——一种基于词频和逆文档频率的词法排序算法——持续优于密集嵌入。原因很简单:BM25 奖励精确词项匹配,而当有人按名称查找特定文档时,专有名词的精确匹配几乎总是正确答案。
生产级企业搜索系统使用混合检索:BM25 和密集嵌入并行运行,其排序结果列表通过倒数排名融合或加权评分进行合并。这既能处理实体查询(BM25 占优),也能处理概念性查询(嵌入占优)。仅依赖语义搜索来处理内部知识库的团队,放弃了只需添加一个 BM25 列就能免费获得的大量检索质量提升。
访问控制必须在检索层执行
RAG 管道中有两个可以执行访问控制的位置。大多数团队选择应用层,因为那里已有现成的授权逻辑。但安全边界应该是向量层。
应用层方式大致如下:无过滤地查询向量存储,检索出 top-k 文档,再丢弃用户无权查看的结果。这有两个失效模式:其一,效率低下——你在获取文档后才丢弃它们,既浪费计算资源,又消耗上下文窗口空间;其二,防御薄弱——如果应用逻辑存在漏洞、做出错误假设或被提示注入攻击绕过,文档依然会流通。
向量层方式将访问控制下推至检索查询本身。索引时,每个文档块被打上代表其访问策略的元数据标签——哪些用户或角色可以检索它。查询时,检索查询包含一个过滤条件,将结果限制在发请求用户有权查看的块上。向量存储从一开始就不返回未授权文档;模型从不处理它。
- https://arxiv.org/abs/2505.01538
- https://weaviate.io/blog/hybrid-search-explained
- https://www.pinecone.io/learn/rag-access-control/
- https://supabase.com/docs/guides/ai/rag-with-permissions
- https://zilliz.com/blog/enabling-fine-grained-access-control-with-milvus-row-level-rbac
- https://medium.com/@michael.hannecke/implementing-row-level-security-in-vector-dbs-for-rag-applications-fdbccb63d464
- https://www.lasso.security/blog/riding-the-rag-trail-access-permissions-and-context
- https://www.elastic.co/what-is/retrieval-augmented-generation
- https://ragaboutit.com/the-chunking-decision-framework-how-enterprise-teams-choose-between-semantic-fixed-and-hybrid-strategies/
- https://community.databricks.com/t5/technical-blog/the-ultimate-guide-to-chunking-strategies-for-rag-applications/ba-p/113089
- https://unified.to/blog/polling_vs_webhooks_when_to_use_one_over_the_other
- https://datanucleus.dev/rag-and-agentic-ai/what-is-rag-enterprise-guide-2025
- https://enterprise-knowledge.com/data-governance-for-retrieval-augmented-generation-rag/
