基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-03 20:15

检索鉴权不能漏掉缓存和关键词分支

dev.to · AI#检索安全#权限控制#Agent
Editor brief · 编辑速览

混合检索的关键词分支、提前返回的缓存以及按 ID 读取等路径,都可能绕过权限控制。文章建议服务端从已验证身份推导读取范围,将权限过滤覆盖所有内容返回路径,并以无权限用户进行针对性探测。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

给 RAG 的向量搜索加上权限过滤,仍然可能泄露数据。关键词搜索、缓存、按 ID 查询,甚至一条指向私有记录的关联,都可能成为另一条入口。原文的结论很明确:凡是能返回存储内容的路径,都必须执行权限检查,读取范围要由服务端从已验证身份中确定。

这篇文章的价值在于把权限问题拆成了可检查的工程细节。不过,它没有实测任何产品:引用的漏洞修复、文档规则、论文结果和作者推断,需要分开看。

搜索加了过滤,为什么还会漏

混合搜索通常有两路:向量分支按语义找内容,词法分支通过 BM25 或 PostgreSQL 全文搜索匹配词语。只给向量分支加租户过滤,关键词分支就可能把受限文档送进合并结果。

相关性决定内容有没有用,授权决定内容能不能被读取。

排序融合不能替代权限检查。原文给出两种统一约束的办法。

一种是把规则放到数据库。PostgreSQL 启用行级安全策略后,普通访问受策略约束,没有策略时默认拒绝。但表所有者通常不受限制,除非设置 FORCE ROW LEVEL SECURITY;超级用户和带 BYPASSRLS 的角色始终绕过检查。应用连接用了什么角色,直接决定策略是否生效。

另一种是给所有检索分支传入同一份过滤条件。Elasticsearch RRF retriever 的 filter 会按各子检索器的规范作用于它们,减少两套过滤逻辑逐渐分叉的机会。OWASP LLM08:2025 提出的权限感知存储要求,也应覆盖混合搜索的第二个索引。

过滤正确,还不等于结果完整。pgvector README 的例子是:近似索引先扫描,再应用过滤;条件命中 10% 的行时,HNSW 默认 hnsw.ef_search 为 40,平均只有 4 行留下。过滤列索引可能让规划器选择精确搜索,这个问题针对的是实际走 HNSW 的情况。

作者据此推测:权限越窄,向量候选可能越少,经 Reciprocal Rank Fusion 或 cross-encoder 合并后,关键词结果的影响可能更大。这个排序变化没有实测,不能当成普遍结论。

pgvector 从 0.8.0 起支持迭代索引扫描,可以继续扫描直到找到足够结果。多租户共享近似索引还可能相互影响召回率和速度,README 建议需要租户隔离时采用 list partitioning 或独立表。因此,只用管理员账号评估检索质量,会漏掉普通用户的体验。

缓存和关联记录,都是读取入口

缓存若在检索前直接返回答案,检索里的权限过滤根本不会运行。

原文引用的团队案例中,一个提示词曾让任意员工看到 HR 文档;但作者没有证据说明这是缓存造成的。缓存风险是另一项推断:应用内的语义缓存或答案缓存,必须把调用者的授权范围纳入匹配条件,或者在返回前完成授权。

HTTP 缓存也不能与应用缓存混为一谈。RFC 9111 §3.5 对携带 Authorization 的请求规定了共享缓存限制,并列出 public、s-maxage、must-revalidate 等允许共享复用的条件。Redis 语义缓存不会自动继承这些规则。

另一类入口是间接引用:ID、精确名称、关联指针、范围参数,乃至查询语言。

开发者 Heinrich Neb 描述过一个实际问题:相似度检索已经正确执行范围限制,按精确名称查询却能向任何人返回完整内容。OWASP API1:2023 对应的要求是,每个接收对象 ID 并操作对象的 API,都应执行对象级授权。

指针还可能只泄露「存在性」。一条公开旧记录仍显示私有后继记录的名称,即使没返回正文,也暴露了隐藏信息。指向的记录是否可见,需要在读取时判断。PostgreSQL 文档也提醒,引用完整性检查绕过行级安全,可能产生隐蔽的信息通道。

查询语言则可能把读取范围进一步扩大。Cognee 的 PR #5844 于 2026 年 10 月 15 日合入 dev 分支,涉及 CYPHER、NATURAL_LANGUAGE 搜索类型执行原始 Cypher 的问题;修复让 ALLOW_CYPHER_QUERY 默认变为 false。原文没有确认该修改进入了哪个正式版本。

隐藏记录与不存在的记录,如果返回不同描述,也会泄露存在性。是否需要统一响应,取决于记录的存在本身是否属于秘密。

谁能决定这次读取属于哪个用户

请求带来的 user_id、租户标签或模型生成的参数,都不能直接充当授权依据。

Databricks agent memory 的 Beta 文档,更新于 2026 年 10 月 26 日,要求应用从可信调用上下文设置 actor_id;依赖终端用户身份时,缺少身份就拒绝,不能回退到共享 actor_id。

原文列出的修复说明了三种不同错误:

  • Supermemory PR #1824 于 10 月 16 日合入工具包 2.x 发布分支。getProfile、documentList、memoryForget、documentDelete 曾直接使用模型提供的可选 containerTag。修复要求标签属于开发者配置的集合,否则在发请求前失败;Tools 3.x 的 #1773 已移除模型选择范围的能力。
  • Mem0 PR #7581 于 10 月 12 日合并,修复 hosted clients 的 delete_all、delete_users 空实体 ID 问题。空 ID 会被 API 当作匹配项目全部记忆。这里涉及删除,且只是客户端修复,原文没有核实服务端后续状态。
  • Anis Meziani 在 10 月 14 日描述,其 ADK-native session routes 原先只验证 token 有效,没有验证 token 代表谁。修复后,所有读取 session 或 memory 的路由,包括实时 WebSocket,都要比对 token subject 与 user_id。

身份验证回答「你是谁」,对象授权还要回答「你能读哪条记录」。

共享记忆还有更深一层边界。Databricks 明确说明,actor_id 用于区分记忆,却不是访问控制;能访问 store 的主体可以读写所有 actor 的条目,严格隔离需要按边界建立独立 memory store。

一篇 2026 年 10 月 19 日的预印本 arXiv 2610.25707 v1,在 AppWorld 中混放了 763 条历史登录信息,对所需应用有 84.7% 的情况检索到其他用户凭据,但 agent 很少实际使用。这个数字受实验设置限制,且论文未经同行评审。给凭据标注所有者能减少其压力测试中的多数误用,却不能替代读取授权。

怎样证明权限检查真的生效

原文提出三组探针,每组都需要有权限用户作为正向对照。否则「什么都没搜到」也可能只是检索坏了。

第一组,在受限文档中选一个稀有词,分别跑 vector-only、lexical-only、hybrid。无权限用户不能取得片段,有权限用户必须能够取得。

第二组,让用户 A 先用受限文档生成答案、预热缓存,再让无权限的 B 提同一个问题及其改写。既要确认 A 确实命中了文档,也要比较 B 在缓存开启和关闭时的授权表现。

第三组,尝试按 ID、精确名称读取,沿公开指针访问隐藏记录,再传入别人的 scope 和空 scope。对隐藏记录的响应,应与不存在记录的响应比较;同时证明有权限身份能够走通该路径。

读取入口要从代码或工具注册表里找。原文引用的一个 MCP 案例中,list_tools 按 token scope 过滤后,旧测试通过了,但持有 tickets:read 的 token 仍能执行删除。工具没有显示出来,不代表底层调用被拒绝。

权限变更和删除后要重跑这些检查,索引与缓存里的权限副本可能过期。检查对象也不能止于最终回答:未经授权的内容一旦进入模型上下文,读取边界就已被跨过。

我的判断

我认同它把审计单位从「搜索接口」扩大到「所有返回存储内容的函数」。这比单纯加强提示词更可靠:模型承诺不引用,无法补上服务端遗漏的授权检查。

但数据库策略、统一过滤参数、独立 store 各有适用前提。数据库策略依赖连接角色正确;统一过滤依赖每个入口都确实使用它;独立 store 能建立更明确的边界,也增加管理成本。原文没有提供这些方案的性能和成本对照,不能据此选出通用最优解。

作者所属公司 Mnemoverse 也被列为文档案例:API key 绑定 organization_id,共享 rooms(beta)每次请求检查成员身份,非成员获得 403,且先检查成员身份再判断归档状态。这是厂商声明的边界,作者没有测试产品,也没有确认引用的各项 PR 是否已经发布。它更适合当审计框架,不能当产品安全排名。

能拿来做什么

  • 给 Node 服务列出所有返回存储内容的入口,包括详情、列表、导出、调试接口和 AI 工具调用,逐项追踪授权范围从哪里产生。
  • 给混合检索建立一份受限文档样本,用两个权限不同的账号分别测试关键词、向量和混合搜索,并按权限层级观察召回质量。
  • 给答案缓存增加跨账号复用、权限撤销和删除后的回归检查,同时查看实际送入模型的上下文。
  • 用 AI 编程助手检查 user_id、actor_id、containerTag 的数据流,重点查找模型参数直接决定范围、空值扩大范围、只验证 token 有效的代码,再人工确认调用链。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
MCP 多语言 SDK 暴露请求体耗尽内存风险
下一篇
重复代码检测:语法指纹与向量为何意见相左

资讯速览

dev.to · AI · 2026-11-03 20:15

AI 评分 8.0 / 10

相关标签

#检索安全#权限控制#Agent

继续阅读

  • 一个 NaN 让已生成的报告无法加载
  • MCP 多语言 SDK 暴露请求体耗尽内存风险
  • 重复代码检测:语法指纹与向量为何意见相左
  • 本地编程 Agent 的提示注入防线怎么建
  • SaaS 模型选型:同时测质量、成本与稳定性