漏洞
菜单里消失的工具,为什么仍会出现在请求里:Open WebUI CVE-2026-45350
CVE-2026-45350 使已登录的 Open WebUI 普通账号能够在聊天请求中点名本无权使用的本地工具或管理员配置的 MCP 连接;在 0.8.6 完成服务端修复前,这些能力可能先被装入对话执行环境,随后才交给模型选择。

文章导航
1 菜单没有显示的私人工具,从请求字段里回到了聊天
先看一个再普通不过的部署。两支团队共用 Open WebUI,管理员把一项远程服务接入事件响应组,并把连接设为私人可见。普通账号新建聊天时,所有选择器里都看不到它,页面像是已经把权限管好了。可请求体仍留着一个能写入工具编号的位置。在受影响版本里,只要编号被带进来,隐藏资源就可能进入对话处理流程。屏幕说“不可用”,服务器却照样把它装进了工具箱。
这点不一致,就是 CVE-2026-45350 的核心。GitHub Security Lab 在复核 Open WebUI v0.6.43 后报告了问题。项目公告把 0.8.5 及以前版本列为受影响,0.8.6 及以后版本列为已修复,CVSS 3.1 评分为 7.1 高危。攻击需要网络可达和一个低权限有效账号,无需另一名用户点击确认。真正的损害大小,取决于被点名工具能做什么,以及连接背后使用谁的身份。
1.1 经过筛选的目录只是权限结果的展示,不是权限判断本身
Open WebUI 会在聊天中呈现本地 Python 工具和服务器工具。可见性设置决定用户应该发现和使用哪些资源,浏览器通常先取得筛选后的列表,再把允许项画在页面上。这对使用体验很重要,却不能替后续 HTTP 请求做授权。浏览器本来就是可编程客户端:开发者工具、脚本、API 集成、抓包后重放的请求、第三方前端,都能绕开选择器直接构造字段。
公开复现把差别讲得很清楚。管理员创建一项外部 MCP 工具,设置编号、地址和所需认证,再把可见性设为私人。随后,低权限用户用自己的有效身份调用聊天补全 API,并在 tool_ids 中写入这个私人编号。项目公告记录的结果是:工具虽然对该用户不可见,仍然被使用。管理员不需要打开聊天,也不需要批准这次调用。
工具编号从来不该被当作密码。即便它看起来随机,也可能留在导出的聊天、浏览器存储、客服截图、日志、配置备份、共享提示、API 跟踪、复制的示例或固定的部署约定里。正确的授权必须在编号已经泄露后依旧成立。隐藏编号至多拖慢发现速度,无法把一次数据库查询变成可靠的访问决策。
请求者确实已经登录。登录解决的是“这次请求是谁发的”,并没有回答“这个账号可以读取哪条工具记录”或“服务器可以替它使用哪项连接”。旧流程拿到了第一个答案,却没有针对每个被点名对象补上第二个答案。这也是项目将问题归为 CWE-862“缺少授权”、CVSS 向量写成 PR:L 而非 PR:N 的原因。
防守时可以画两列账。左边写页面当时展示了什么,右边写服务器最终解析了什么。安全请求的右列只能包含当时确有权限的资源。受影响请求则可能在右列出现一个隐藏编号,即使左列从未展示它。历史调查必须还原两列内容;一张菜单截图证明不了模型实际收到的可调用集合。
这一区分也能防止把结论说过头。公告没有声称每个普通用户会自动拿到全部工具。请求者需要点名资源,部署中需要存在这项资源,补全流程也需要成功加载它。之后是否调用,还受提示、模型行为、工具调用模式和可用定义影响。这些条件会缩小单个事件的范围,却不会补回缺失的服务端判断。
公开的 CVSS 向量也给出了精确刻度。AV:N/AC:L/PR:L/UI:N 表示路径可经网络触达、复杂度低、需要低权限账号、无需额外用户交互;S:U/C:H/I:L/A:N 评估为高机密性影响、低完整性影响、范围未改变、没有计入可用性影响。实际部署可根据真实工具重新排优先级,但不能把通用分数写成某条记录已经失窃或某套系统已经被改动的证据。
1.2 后果由被选中的能力决定,不由聊天框的外观决定
聊天界面很容易让人误以为这是提示词处理问题。真正被越权选择的对象比文本强得多。本地工具记录可以让 Open WebUI 加载 Python 函数,绑定名为 valves 的配置,把函数签名转换成模型可见的定义,再保留可供执行的调用对象。MCP 连接则可能携带远程地址、认证方式、密钥材料以及另一套系统提供的方法目录。
所以每个安装的影响都不同。只读取公开文档的演示工具,可以低风险地证明授权失败;能够检索内部工单、读取代码仓库、查询客户资料、改变云环境或触发部署的私人工具,则携带这些动作本身的权限。CVSS 给出产品层面的共同基线,运营团队仍需盘点本机能力,才能决定先查哪一条连接。
即使调用没有完成,方法定义的泄露也有价值:函数名、说明、参数形状和错误信息可能暴露内部服务具备哪些能力。更大的问题是执行。模型一旦在可用集合里选中该方法,Open WebUI 就可能调用它。公开公告明确指出,服务器保存的认证令牌会被用于调用,因此低权限网页账号与远端服务识别的主体可能并非同一个人。
权限错误并非模型制造。模型收到函数定义时,应用代码已经决定哪些能力可以进入环境。模型可能拒绝调用,可能在明确提示后调用,也可能在工具推理时自行选择。任何一种概率结果都不能充当访问控制。可靠做法只有一个:推理开始前,就把无权使用的定义和调用对象排除掉。
事件响应也应按阶段下结论。先确认无权资源是否被解析,再确认定义是否进入补全请求,然后判断模型是否产生工具调用,最后把调用与本地副作用或远端审计记录对应起来。从一个请求编号直接跳到“数据已泄露”,会超过证据;只看菜单说“用户看不到”,又会遗漏公告已经证明的服务器行为。
凭据处置同样需要这条顺序。若日志能证明某项连接从未配置或从未被触达,仅因存在受影响版本就轮换所有令牌,未必是最高效的动作。一旦越权请求已经初始化连接、远端记录显示方法执行,或日志太弱无法限定使用范围,轮换就应立即进入处置计划。能力大小、事件阶段和证据质量必须一起判断。
调查优先级最好预先绑定数据分级。只检索公开手册的工具可以放在较低级别;能读取法律案件、薪资、生产仓库或客户支持导出的连接,即使只有读权限,也应进入高优先级。含有删除、合并、部署、邀请或凭据管理方法的工具,还会增加完整性风险。分级不负责证明利用,它负责在时间有限时告诉团队先保存哪一批证据、先控制哪一项身份。
最终需要回答的是两个人的故事:谁在 Open WebUI 发起请求,谁在目标系统执行动作。只保存网页账号,会看不到远端令牌的权限;只保存远端服务账号,又会把异常操作误当作正常集成流量。图 1 把这两个身份拆开,后面的源码与调查都会沿着这条线继续追下去。
2 一次已认证请求,把不可信的资源选择送进了可信中间件
读源码时,可以把请求想成一只贴着两张标签的包裹。认证中间件贴上已经核验的用户身份,客户端则写入模型、消息和工具选择。process_chat_payload() 同时收到两者,随后整理元数据、解析资源、准备函数定义,再把结果交给补全与执行阶段。问题就发生在可信身份与不可信选择相遇的地方。
这条路远不止查一次数据库。它会从表单移出控制字段,解释编号,找到本地记录或服务器连接,取得方法定义,把请求上下文装进调用对象,将不同来源合并进同一个字典,最后把字典交给模型。每一步都在增加权限含义。起点少做一次判断,终点就可能多出一项可执行能力。
2.1 chat_completion 确认请求者身份,process_chat_payload() 解释请求者提交的对象编号
受影响 API 接收的是已认证补全请求。GitHub Security Lab 链接的 v0.6.43 源码中,路由把请求体和用户对象交给处理中间件。这个用户对象包含后续控制可用的账号编号与角色。认证确实存在,也确实有用;缺的是在选中工具生效前,针对那条记录做一次明确的读取权限判断。
process_chat_payload() 会从表单数据中取出 tool_ids,并把它保存在请求元数据里;其他元数据还能描述服务器工具。把字段移走不等于校验,只是把外部请求形状转换成内部执行形状。转换后,如果日志只记录发往模型供应商的请求,原始选择可能已经不在顶层。应用必须在转换前留下自己的审计事件。
列表内容与顺序都由客户端控制。它可以包含一个编号、多个允许编号、允许和拒绝项的混合、服务器形式编号,或根本不存在的值。稳健实现会逐个判断已经解析出的对象。只跳过未知项,仍会放行已知的私人对象;发现一个合法项后整体接收列表,又会让合法项把旁边的禁止项一起带进去。
直接使用 API 并不属于离奇场景。公开复现使用管理员开启的 API 密钥,由普通账号发起请求,符合公告给出的低权限认证条件。把它称作“绕过浏览器”无法降低问题,因为这条路本来就应对所有受支持客户端保持同样的安全属性。
这也说明提示词过滤修不好根因。规则可以拦截“私人工具”或某个方法名,工具选择却位于结构化字段中;定义一旦出现,模型还可能从普通自然语言推导出调用。资源授权拥有两个精确输入——用户与对象——可以给出确定结果。自然语言筛查既缺少这种精度,也无法覆盖每种表达。
最有价值的跟踪点位于认证之后、工具解析之前。事件可记录请求编号、用户编号、角色、本地工具编号、服务器连接编号、聊天编号、模型、来源地址和时间。敏感消息正文可按另一套保留规则处理。这条小记录恰好保存了旧路径没有回答的问题,也便于日后与权限历史做关联。
反向代理通常只记录方法、路径、状态、耗时与请求体大小,不会保存 JSON 正文;模型供应商看到的又可能是 tool_ids 被移出顶层后的补全格式。两边都很有用,却都不完整。Open WebUI 是唯一同时掌握已认证用户和原始工具选择的位置。重视隐私的实现可以对聊天与密钥编号做哈希,只保留权限复核所需的资源编号,完全不记录消息内容。
跟踪时还要区分三份形状:客户端原始表单、中间件整理后的元数据、送往模型的函数定义。原始表单说明用户主张使用什么;元数据说明应用怎样解释主张;模型载荷说明最终暴露了什么。把同一请求编号贯穿三份记录,就能定位编号究竟在哪一步被接受或排除,也能在未来重构字段时避免审计断裂。
2.2 本地函数和远程方法最终汇入同一个可调用字典
中间件需要把不同来源变成统一集合。本地 Python 函数和远程 MCP 方法都要有名称、说明、参数定义与执行适配器。Open WebUI 把这些项放进工具字典,再转换成模型可理解的函数格式。统一结构便于产品扩展,也意味着禁止项一旦进入字典,后续代码就会把它当作普通合法能力处理。
本地记录会由 get_tools() 通过 Tools.get_tool_by_id() 解析;应用随后取得或加载模块,组合全局与用户 valves,检查已声明函数,再建立调用项。服务器记录则由中间件找到连接,准备认证和客户端会话,取得远端方法定义,并包装调用,让模型后续的选择能抵达该服务器。两条支路在模型使用前汇合。
函数重名处理能看出对象已经被接纳到什么程度。如果另一项工具占用了相同方法名,代码会给名称加上工具编号前缀,直到字典键唯一,然后写入 tools_dict。此时下游只看到一个结构完整的调用对象。除非解析器提前判断并记录权限,下游已无法从改名后的函数恢复原本的可见性设置。
工具补全至少存在两类实现:模型或供应商原生支持函数调用;应用也可以把定义序列化后交给任务模型,再解析它选中的函数。两种模式都消费同一份已组装集合。若授权只绑在某一家模型、某个提示模板或某条解析路径上,另一条模式仍会漏掉。控制点必须放在资源进入公共集合的位置。
调用结果可能变成对话文字、引用、文件或嵌入式界面,事后清理很难覆盖全部渠道。即便远端方法只有读权限,它返回的敏感文字也可能被保存、流式发送、建立索引或展示给后续参与者。可写方法造成的外部状态变化,更不是删除聊天就能撤销。入口处排除禁止项,比逐个清理结果通道可靠得多。
流式响应不会改变控制点。一次补全可以先输出文本片段,随后分块发送工具调用外壳和参数,最后再返回结果;可调用集合仍在这些片段引用函数前完成。如果日志保存了所有流片段,却没有保存最初的授权集合,调查会又吵又缺关键证据。更好的做法是先记录集合摘要及逐对象结论,再把后续每个片段和调用关联到该摘要。
因此,图 2 追踪的是组装过程,不需要假定模型一定会调用。安全关键时刻是可调用集合被填充的那一刻。拒绝对象必须在定义序列化、模块加载、凭据读取、网络初始化和名称去重前消失。“这次模型没选它”只是一次执行结果,证明不了访问控制正常。
3 本地工具支路把一条数据库记录变成了应用内的执行能力
第一条支路从一次很短的查询开始。工具编号进入 get_tools(),Tools.get_tool_by_id() 取出保存的记录。接下来,应用可以加载相应模块,组合配置与用户上下文,检查公开方法,再生成可调用定义。工作区目录里看似普通的一行数据,实际上是通往 Open WebUI 进程内代码的入口。
这也解释了为什么等模型选中函数后再判断已经太迟。模块解析、配置访问、定义生成和函数注册,都发生在可调用集合组装阶段。被拒绝的资源不应参与其中任何一步。项目公告指出的第一次修复,把读取决策移到模块加载之前:没有经过授权读取,就不能出现在返回字典里。
3.1 get_tool_by_id() 只回答对象是否存在,旧解析器却把存在当成了可用
受影响的模型方法本身很简单。收到编号后,它打开数据库会话,获取对应 Tool,再把结果转换成 ToolModel。作为底层存储函数,这很合理:它回答对象是否存在并返回字段。它不知道请求账号是谁、属于哪些组,也不知道当前操作需要哪种权限。
旧解析器在处理客户端提供的编号时调用了这个底层函数。GitHub Security Lab 记录的路径没有在记录继续向前前比较所有者,也没有做等价的读取判断。当前用户已经传给外围函数,问题并非缺少身份输入;缺的是把这个身份和当前记录放在一起进行策略计算。
“不存在”和“存在但无权”应有不同的内部结论。不存在的编号可以跳过或记为缺失;存在但禁止的编号应被排除,同时不要向客户端泄露有助于枚举私人记录的细节。对外可以给出相同结果,对内日志仍可区分 unknown 与 denied。这样既保护资源隐私,也保留调查所需证据。
记录继续向前后,解析器会先在应用缓存中寻找模块,找不到时可按工具编号加载。Python 模块加载可能在任何公开方法被选择前初始化对象并执行模块级语句。公告确认的是“未授权使用工具”;无需再假设额外副作用,也足以判断禁止模块不应在权限决策前被加载。
随后,解析器准备当前用户、请求辅助对象等特殊参数,还会读取工具保存的 valves 以及账号自己的 valves。这些值可能包含服务设置、目标或函数运行所需的选择。最终得到的对象并非静态源码说明,它已经带着配置和已认证请求的实时上下文。
函数检查会把方法转成名称、说明和允许参数。若两项工具声明同名方法,代码可不断加上工具编号前缀,直到名称唯一。这个步骤说明记录已经成为执行环境的一等成员。权限必须在名称标准化之前判断,因为下游无法仅凭改写后的函数名找回原始对象的分享状态。
整条旧路可以拆成四个状态:请求点名对象、数据库取出记录、模块加载并绑定配置、模型获得可调用项。调查时应尽量分别保存。请求体只能证明第一步;解析日志能证明第二步;缓存或加载跟踪支持第三步;序列化定义或工具调用记录才支持第四步。结论强度应跟随实际观察到的最深阶段。
函数定义与真正调用对象也应分别观察。名称、说明和参数结构可能已经序列化给模型,但 Python callable 尚未执行;反过来,某些应用管理模式会在服务端完成选择后直接运行 callable。测试夹具应给定义生成和函数入口各放一个独立标记,避免把“模型见过方法”和“方法已经运行”写成同一事实。
3.2 本地修复先检查角色、所有者、组成员与读取权限,再允许代码加载
提交 9b06fdc8fe1c933071610336be05f11e77e6c8eb 改变了顺序。解析器先取得请求者的组编号,再读取每个被点名记录,并检查三条允许路径:部署开启 BYPASS_ADMIN_ACCESS_CONTROL 时管理员可以通过;记录所有者可以通过;其他账号则必须由 has_access() 根据工具读取策略和当前组集合确认。
三条路径都不满足时,固定代码写入包含用户与工具编号的拒绝警告,然后继续处理下一个编号。它不会加载模块,不会设置 valves,不会检查函数,也不会把调用对象写入结果。“继续”对混合列表很关键:一个拒绝项不会影响邻项,一个允许项也不能替其余对象背书。
所有权、分享和管理员策略是三种不同来源。所有者因记录归属而使用对象;用户或组授权在不改变所有者的前提下扩展读取;管理员绕过则受明确配置开关控制。若把三者压成一个“可见”布尔值,日后很难解释某次请求在某个时间点为什么被允许。
组成员关系也必须按事件时间复原。员工后来换组后,当前数据库快照可能错误判断旧请求。工具访问设置、所有者和管理员策略同样会变化。高质量审计需要版本化的组分配、授权变更、对象更新、管理员设置和实际执行代码。没有历史时,今天的 has_access() 结果无法裁决几个月前的聊天。
修复放在 get_tools() 内,可覆盖所有使用该解析器的补全入口,也降低了对目录接口的依赖。新界面即使忘了筛选菜单,自定义客户端即使直接发送编号,最终解析仍会执行对象策略。AI 中间件可能不断增加供应商、提示模板和调用模式,但资源判断的位置可以保持稳定。
回移时应保留行为,不要只复制几行。不同分支可能以另一种方式保存组编号,使用不同访问结构,在别处缓存模块,或给解析函数换了名字。验收条件仍然清楚:禁止编号不会产生调用项;该请求不会因禁止编号加载模块;所有者和明确共享对象仍可工作;撤销组成员后下一次决策立即生效;管理员行为符合部署设置。
缓存还需要两组断言。合法请求把模块留在全局缓存里,可以是正常性能优化;之后的无权请求仍必须在把缓存对象加入自己字典前失败。反过来,拒绝某个账号也不能破坏合法账号对同一模块的使用。策略控制的是“谁能用”,缓存控制的是“对象活多久”。把“已经加载”误写成“已经授权”,只会让原来的错误走上一条更快的路。
源码复核还应搜索绕过固定解析器的兄弟入口。列出、编辑、删除、导入和执行工具是不同操作,可能各自拥有路由。CVE-2026-45350 的公开范围是聊天补全中的选择路径。检查相邻入口属于防守完整性工作,不代表这些入口已经被证实存在同一漏洞;若发现独立问题,仍需单独复现与协调处理。
4 MCP 支路借用了管理员配置的身份,目的地却由请求者选择
远程支路的风险更高,因为被选择的是一项连接,不只是函数目录。Open WebUI 可以保存服务器地址、连接类型、认证方式、密钥、连接配置和访问授权。准备聊天时,它能够联系服务器、列出远端方法、转换参数定义,再建立调用适配器。请求负责选中连接,应用负责提供连接背后的权限。
GitHub Security Lab 用公开 fetch 服务演示,让授权失败能够在不触碰私人系统的条件下被观察。相同应用路径也可以指向任意管理员配置的 MCP 服务。因此,公告把影响写成能力范围:受限工具可能被调用,服务器保存的认证可能被使用。它没有声称每个部署都会暴露同样的数据,也没有声称每项连接都拥有写权限。
4.1 连接查询之后,旧流程才会读取认证、建立网络会话并发现远端方法
服务器形式的编号告诉中间件要找哪条连接。代码在配置集合中搜索对应编号;找不到时可以记录并跳过,找到后则拿到下一阶段所需信息:服务器类型、地址、认证模式、密钥或会话行为、方法过滤和连接设置。
一旦“找到”被误当成“有资格使用”,风险顺序就开始了。应用可从记录组装认证头,创建 MCP 客户端并连接地址,请求远端工具目录,再把每项定义过滤、标准化和包装,让后续工具调用把参数送到同一服务器。此时,低权限账号已经影响了一个使用应用凭据建立的网络会话。
MCP 把发现与调用分开。客户端先通过 tools 能力取得名称、说明和输入结构,再为选中的名称发送参数。这带来两个可独立观察的里程碑:成功列出方法,证明 Open WebUI 在某个连接上下文中抵达远端;成功调用,才证明某个方法执行。远端审计应分别保存两者,因为“只列出未调用”和“已经改变数据”的含义完全不同。
密钥不需要出现在聊天文字里,也一样会构成安全问题。服务可以替错误的网页用户使用凭据,同时不泄露任何令牌字节。关键是权限被谁使用:远端识别了哪项身份,这个身份能访问哪些方法,这些方法接触了哪些对象。只扫描聊天中的密钥适合发现另一类事故,发现不了这种代为调用。
网络位置还会扩大实际可达范围。Open WebUI 服务器可能连接用户工作站无法直达的内部名称和地址;MCP 服务又可能继续连接源码、工单、存储或编排 API。CVE-2026-45350 没有凭空创造这些集成,它让错误账号有机会选中已经存在的连接。范围评估应从真实连接清单和远端审计出发,不能拿 MCP 理论上能接的所有系统填空。
错误结果也是证据。远端拒绝某个方法,可能说明连接已初始化、调用已尝试,同时限制了最终损害;超时可能只支持一次网络尝试;返回方法定义能证明发现,却不能证明调用;远端审计、返回对象编号或下游状态变化,才是更强的执行证据。按阶段归类,既避免虚假放心,也避免没有依据的升级。
正确控制点紧跟在连接查询后、读取第一项敏感字段前。此时应用已经拥有请求用户和连接授权设置,足以确定允许或跳过。若把判断放在读取密钥、打开套接字或列出方法之后,可能拦住部分执行,却仍然触发了无权账号不该触发的动作。
每条连接的方法过滤是一项有用的第二层控制,但替代不了连接授权。它可以从合法用户的目录中去掉高影响方法,也能缩小共享集成提供的功能,却回答不了这个用户是否能发现和使用整条连接。回归测试应验证两个嵌套集合:账号允许的连接,以及每条允许连接内可用的方法。若先接纳了禁止连接,再做方法过滤,外层对象已经选错。
MCP 授权规范描述客户端与服务器如何取得和使用令牌,但 Open WebUI 仍需先决定哪个网页用户可以启用哪项已配置客户端。协议层认证解决连接向远端证明身份,应用层授权解决本地账号是否可以借用这项连接。两个问题处在不同层次,任何一层正常都不能自动证明另一层正常。
4.2 远端只看到连接账号,响应团队必须把两套审计记录拼到同一事件
Open WebUI 知道谁发起聊天,MCP 服务器却可能只认连接携带的 bearer 或其他凭据。没有关联时,远端日志会像一项可信集成的日常活动。陷阱就在这里:上游请求者和下游主体不同,却描述同一件事。如果两端都能记录同一个请求或跟踪编号,这是最干净的桥。
没有公共编号时,可按时间、目的地、方法、参数摘要、响应大小、聊天编号和来源主机进行关联。时钟同步很重要。流式补全与重试会把一次交互拉长几秒,也可能重复 list 和 call。保存带时区的原始时间与测得的时钟偏差,之后再统一时间线。
连接能力应按事件日期复原。远端服务器会更新:方法增加,说明改变,令牌角色也会变化。今天的 tools/list 不一定等于受影响请求当时看到的目录。配置备份、部署提交、MCP 服务版本和审计元数据可以恢复旧状态。若历史缺失,应明确写出不确定性,不能把当前目录当成过去事实。
参数可能包含秘密或受监管数据,保存时要克制。若政策禁止保留完整内容,可保存哈希和必要元数据。代码仓库方法可记录组织、仓库、操作、对象编号与结果;工单方法可记录项目、工单号、操作和附件数量。目标是证明动作与范围,同时避免把敏感资料复制进调查系统。
凭据轮换依据是已观察使用或无法限定的使用。替换 MCP 令牌只能关闭未来会话,不能撤销已完成动作。还要查看下游对象历史、权限变更、webhook、导出,以及工具可能读取到的二级凭据。远端没有完整审计时,记录缺失会降低结论信心,不能被写成路径从未运行的证明。
最小权限能在修复前后限制影响。只读检索连接不应和可写自动化共用身份;不同连接可以拥有不同授权、令牌、目的地与告警。短期令牌、目的地址白名单、方法过滤、按组明确分享,都能减少一次选择获得的权限。这些措施用于补强固定版本,不能把 0.8.5 变成安全版本。
远端限流和审批也可能缩小已经开始的调用,却同样需要进入证据。服务也许拒绝第六次请求,要求写操作审批,或允许搜索但拒绝导出。每个结果都会改变实际损害,却不会消除上游授权失败。成功与拒绝的方法都要保存,因为连续拒绝仍可证明无权账号把服务器连接推进到了受保护操作。
现在可以准确重放开头:普通账号提交私人连接编号;旧中间件找到记录,应用保存的身份被用于建立会话,远端方法进入补全环境。固定路径会先计算该账号对连接的权限。拒绝账号不会触碰认证解析、客户端初始化、方法发现或调用包装。
若连接使用 bearer,远端通常只看到保存令牌对应的主体;若使用其他受支持认证形态,具体日志字段会变化,但调查问题不变:Open WebUI 哪个账号触发了这次会话,目标系统把动作归给谁。响应手册应为每条重要连接预先写明远端日志位置、主体名称、保留期和负责团队,事故发生后才不需要临时寻找所有者。
5 两段修复历史最终汇到同一个运营底线:Open WebUI 0.8.6
公开记录里有两只容易被压成一只的时钟。提交 9b06fdc8fe 重构工具解析并加入访问判断,随后进入 1 月 9 日发布的 v0.7.0。提交 4737e1f118 后来增加通用连接访问函数,v0.8.6 的 MCP 解析会使用它,该版本于 3 月 1 日发布。5 月公开的项目公告把本地工具记录对应到第一次修复,把管理员 MCP 连接的公开复现对应到第二次。
对运营团队来说,公告已经回答版本问题:0.8.5 及以前受影响,0.8.6 及以后才是完整固定底线。源码历史仍有用,因为私有分支和发行包可能挑选部分提交,却没有采用正式标签。可信回移必须证明两类资源都在敏感动作前做权限判断,并正确处理所在分支的数据迁移。
5.1 v0.7.0 重构把访问判断放进本地解析,后来的 MCP 路径仍需独立验收
公告历史里的第一个提交虽然主题只有“refac”,变更范围并不小。差异把本地工具组装整理成更清楚的循环,读取组成员,判断所有者和读取权限,并为服务器连接增加辅助函数;该提交当时修改的服务器路径,也把检查放在认证字段前。这些事实可以从提交直接看到,对下游复核很有价值。
但项目公告仍把两个固定版本明确拆开:本地 Tool 记录首次修复在 v0.7.0,公开复现使用的管理员 MCP 服务器形式首次完整修复在 v0.8.6。运营应保留这一区分。中间版本里找到一个名称很像安全检查的函数,证据强度仍低于用实际请求形状测试已交付构建。
从受测 v0.6.43 到 v0.8.6,产品结构一直在变化。工具服务器连接数据、原生工具支持、终端集成和公共访问函数都发生演进。一条解析器有检查,不代表另一种记录形状或入口自然继承同样策略。这也是安全公告倾向给出固定版本,而不要求用户从孤立差异自行推断安全状态的原因。
验收必须落到真正应答补全请求的副本。记录包版本、镜像摘要、仓库修订、私有补丁、进程启动时间和服务 pod 或主机;滚动升级时排空旧副本,让新摘要通过就绪检查及允许、拒绝对照后再接流量,并确认残留 worker 已退出。镜像已下载、标签已更新或仓库已有修复,都不能代替运行进程证据。
私有回移要保存父提交和差异说明,并从拒绝后的 continue 向前确认用户与授权,向后确认凭据和网络尚未使用,再用运行测试证明顺序。若其他回归迫使版本降到 0.8.6 以下,应停用高影响工具、移除保存凭据或限制补全端点,不能把重新隐藏菜单当作安全回退。
5.2 v0.8.6 公共函数统一连接授权,并把判断放到了凭据使用前
提交 4737e1f11847d057859ec78892fa89e24cbcd83b 在公共访问工具中加入 has_connection_access()。它接收当前用户、连接字典和可选的组集合。部署开启管理员绕过时,管理员可以通过;config.access_grants 为空或缺失时,连接被视为向所有用户开放;存在授权时,再由 has_access() 根据账号和组计算读取权限。
“空授权即开放”在处置时必须讲清。这个数据模型里,没有 grant 不等于私人。管理员若要限制连接,需要写入有意义的访问授权,并用非成员账号实际验证。迁移时若字段丢失或名称不对,即使代码已经固定,也可能把原本想限制的连接变成公开。
同一提交还包含 migrate_access_control(),用于把旧访问字段转换到新的 access-grants 形状。回移和升级后应检查持久化连接,尤其是配置曾经过环境变量、数据库、JSON 导出或管理界面时。解析器只能根据自己真正读到的策略数据做决定。
中间件从较早的工具服务器专用函数切换到 has_connection_access()。拒绝支路写入服务器与用户编号,然后在读取认证类型、客户端继续运行前跳过。这个顺序就是运营可以观察的安全属性。辅助函数叫什么并不重要,跟踪记录必须显示拒绝先于密钥访问、DNS、套接字、初始化、发现和调用包装。
公共函数还可以减少连接型功能之间的漂移。工具服务器和终端服务器能够共享授权语义,同时保留各自执行逻辑。公共策略代码只有在每个敏感调用者都提前使用时才有价值。代码搜索应列出所有读取连接地址、密钥和授权字段的位置,逐个确认它们都会做同一判断。
升级测试必须同时覆盖开放连接和受限连接。空授权连接若确实设计为开放,应继续工作;用户授权和组授权应能放行;非成员应被拒绝;管理员行为应符合 BYPASS_ADMIN_ACCESS_CONTROL。这组测试既发现迁移造成的意外锁死,也发现迁移造成的意外开放。
v0.8.6 发布说明主要描述产品功能,之后公开的安全公告才给出权威的受影响与固定映射。协调漏洞先进入代码与版本、后公开安全解释,是正常发布顺序。运营应分别使用公告判断安全状态、使用标签确认包来源、使用提交复核实现;三种来源没有任何一个能单独回答全部问题。
因此,最稳妥的版本结论很短:使用 0.8.6 或更高版本,重启所有服务进程,确认实际摘要,分别证明本地和 MCP 支路。提交存在能帮助解释回移,却代替不了运行证据。图 5 把两段历史分开,直到它们在同一个验收点汇合。
6 有效回归不仅看返回值,还要看拒绝之后哪些事情从未发生
只看 HTTP 状态码证明不了修复。补全端点在静默排除禁止工具后,仍可能正常回答;下游模型也可能因无关原因失败。决定性断言是“缺席”和“顺序”:禁止资源不在调用集合,代码与凭据没有被触碰,网络副作用没有开始。同一测试里的允许资源还必须成功,证明测试确实走到了目标支路。
测试环境既要足够小,能讲清每个对象,也要覆盖策略。两个普通用户、一个管理员、两个组、一项自有工具、一项直接共享、一项按组共享、一项私人本地工具、一条开放 MCP 连接和一条受限连接,构成实用基线。每个对象使用稳定编号,每项敏感操作都设置可观察计数或跟踪标记。
6.1 本地回归证明禁止项在模块导入、配置读取和定义生成前被排除
先建立无害本地夹具:模块加载时增加一个计数,valve 访问时增加另一个计数,函数调用时再增加一个,函数只返回固定值。它不需要模拟危险集成,目的只是暴露执行顺序。每次请求前清空计数,防止前一个允许测试污染拒绝测试。
用非所有者账号发送认证补全请求,点名私人夹具。响应可以是普通模型回答,真正要看的是服务器状态:应出现该用户与工具编号的拒绝事件;模块加载计数不变;valve 未被访问;序列化工具集合没有该函数;调用计数为零。若另一项测试已把模块放入缓存,就在解析位置增加与缓存无关的探针,或让拒绝用例在新 worker 中运行。
接着依次测试所有权、直接读取授权、匹配组授权和配置的管理员策略。每个允许用例都应产生定义,并在模型和提示可控时完成一次无害调用。随后撤销授权,再发新请求;下一次解析必须拒绝。长期聊天不能把昨天的调用集合变成撤销后仍永久有效的能力。
混合列表不可省略。先放允许编号再放禁止编号,交换顺序,放两个禁止项,再加入未知项。输出必须精确等于授权子集。任何对象都不能继承前一项的结果;一个格式错误编号触发异常时,也不能回退到未经筛选的原始列表。逐对象记录判断原因,能让这一点直接可见。
函数重名提供另一组负例。让允许工具和禁止工具声明相同方法名。禁止项必须在重名处理前消失,它的编号前缀不应出现在可调用集合、面向用户的日志或供应商载荷里。这证明排除发生在标准化还没有遮住来源对象之前。
部署若同时支持原生函数调用和应用管理的函数选择,两种模式都要测。因为它们消费同一授权结果,预期集合必须一致。供应商故障、模型拒绝和提示差异都不属于权限断言。直接检查组装后的定义,避免模型选择掩盖解析器回归。
并发也需要受控用例。让合法与拒绝账号同时请求同一缓存工具,再让请求交替经过不同 worker。允许请求可以使用模块;拒绝请求即使撞上缓存填充,也不能得到调用项。这个测试守住全局实现缓存与逐请求权限的区别,而单线程单元测试很容易看不到它。
界面自动化只能作为补充。真正失败的是服务器接受客户端选择,因此回归必须直接构造 API 请求,明确写入工具编号,再检查服务端结果。浏览器用例可以验证菜单继续正确显示,却不应成为唯一安全测试;否则将来页面仍然隐藏私人项时,解析器回归可能再次被漂亮界面遮住。
6.2 MCP 回归必须在密钥访问、DNS、套接字、初始化和 tools/list 前停止
远端夹具需要可观察的连接对象和服务器。分别包裹认证字段访问、域名解析、客户端构造、会话初始化、方法列出和方法调用,给每步设置独立计数。拒绝请求只能增加授权判断计数。即使只是连接模拟服务器,对拒绝用例也已经太晚;“没有网络活动”本身就是被测试的属性。
对于空授权开放连接,应明确验证它按设计放行;对于受限连接,测试用户授权、匹配组、不匹配组、撤销成员和管理员绕过开关。每次保存实际参与计算的 access-grants。迁移测试还应加载旧配置形状,执行项目迁移,再确认最终语义。
允许调用应给出正向顺序:放行、读取认证类型、取得凭据、初始化客户端、列出工具、公开选中定义,最后调用无害方法。这条跟踪是拒绝路径的参照,使“提前停止”能够被证明。夹具方法可返回唯一请求标记,方便识别重试。
再测试“发现但不调用”。允许连接并列出方法,然后让模型或测试框架不选择任何函数。这能区分远端可达与方法执行。之后执行一次受控调用,确认远端审计含有预期连接主体、方法、参数和关联标记。两组用例也会训练调查人员,不把两个阶段混成一个。
授权通过后的失败同样要覆盖:无效凭据、主机不可达、初始化错误、列出失败、未知方法和远端拒绝。它们应被记录为连接或工具故障,不能被误记成授权拒绝。因为用户有资格尝试连接,权限事件本身仍是允许。分类清楚,可靠性事故才不会被统计成拦截攻击。
多 worker 测试应在滚动升级前后交替请求。每个 worker 都必须在密钥访问前拒绝受限连接。隔离测试环境可保留一个故意过时的 worker,用来证明路由和版本遥测能识别它。生产升级完成后,不应再收到旧摘要返回的响应。
异常策略也要定义为安全失败。若组查询或受限连接的授权解析报错,请求不能为了可用性继续使用保存凭据;同时,策略格式错误应产生不同于普通拒绝的运维信号。用受控的无效授权对象测试,确认跟踪在连接动作前结束,管理员还能得到足够上下文修正配置。
测试结果还需区分“拒绝成功”和“系统失败”。前者有明确访问结论,后续敏感计数为零;后者可能因数据库、组服务或解析异常提前退出,却没有可靠权限结论。若把所有异常都当成安全拒绝,真实用户会遇到故障,团队也会误判控制有效。断言应同时检查决策类型、错误类别和副作用计数。
时间相关用例也要加入矩阵:授权在请求前撤销、解析后调用前撤销、连接已建立后撤销。项目固定点首先保证每次资源解析时正确判断,系统设计还需明确已经开始的调用如何处理。测试应记录实际语义并让高影响操作符合组织政策,不能让会话缓存把撤销无限期推迟。
每次回归都应保存一份可比较的授权集合摘要。升级前后若允许项发生变化,测试报告必须说明是修复预期、配置迁移还是意外差异。只验证禁止项消失,可能漏掉合法工具被错误删除;只验证合法项可用,又会漏掉私人项仍混在集合里。集合级比较能同时守住安全与功能。
7 调查先盘点真实能力,再沿每次请求向下追踪
升级能回答“以后还会不会发生”,事件调查要回答“升级前发生过什么”。版本号本身给不了答案。没有任何私人连接的受影响安装,与连接了管理员服务的安装,历史风险完全不同;即使确有受限资源,也要证明普通账号是否点名、解析、发现或调用过它们。正确顺序是先做能力清单,再查请求,最后查副作用。
证据保存和修复可以同时进行。日志保留期或升级可能覆盖数据,操作前应快照相关配置、授权表、组成员、应用日志、反向代理记录、聊天元数据、容器身份和远端审计。随后立刻部署固定版本并缩小权限。公开源码和公告已经证明机制,没有必要为了复现把脆弱 worker 留在线上。
7.1 还原一个事件,需要请求、历史策略、调用集合和下游结果四类证据
先导出受影响时期存在的全部本地工具与连接。本地工具记录编号、所有者、创建和更新时间、模块修订或哈希、函数名称、访问设置、全局 valves 以及安全相关能力;连接记录编号、服务器类型、地址、认证方式、授权配置、凭据所有者、远端主体、方法允许列表和该主体可触达的系统。
接着建立历史策略视图。组成员、直接授权、对象所有者、管理员角色和 BYPASS_ADMIN_ACCESS_CONTROL 都会改变。数据库审计、身份提供方日志、配置仓库、备份和管理事件可以补全时间线。若只剩当前状态,就把过去权限标为未解决,不能默默把今天的组关系套到几个月前。
然后提取聊天与代理事件。重要字段包括时间、请求编号、用户、API 密钥、聊天和消息编号、来源地址、客户端、模型、工具选择模式、请求工具编号、响应状态、耗时与服务修订。有些受影响版本可能没有直接记录选择;聊天元数据、保存的请求体、跟踪系统、供应商载荷和错误信息可部分恢复。
针对每个编号,标记观察到的最深阶段:已请求、已找到、按历史策略本应允许、进入调用集合、从远端发现、被模型选中、已调用、返回数据、产生可验证副作用。“历史策略本应允许”要和“旧构建没检查”分开。用户即使经过有缺陷的代码,也可能当时确实拥有合法权限。
本地执行证据包括应用日志、函数自己的审计、进程创建、文件访问、数据库查询、外连、生成文件和工具结果引用。具体信号由工具实现决定。模块哈希必须保留,因为方法名称和代码后来可能改变;今天看起来无害的版本,不能证明旧修订当时做了什么。
远端证据包括 DNS、代理、防火墙流量、MCP 服务器日志、身份提供方令牌使用、方法审计、访问对象编号、导出、写操作和 webhook。关联窗口需考虑流式响应和重试。一个连接账号服务多个 Open WebUI 用户时,远端日志通常无法单独识别发起者,应用请求正好补上这块归属。
高优先级模式包括:普通账号点名目录里没有的编号;连续提交未知或拒绝项;在一串编号中快速尝试;请求后紧接敏感远端方法;返回量异常;调用聚集在授权变更附近;平时很少用工具的 API 密钥突然大量选择资源。这些是调查线索,不能单独证明利用,仍需与资源和下游记录核对。
负面证据也要说明覆盖。“完整 MCP 审计保留 30 天,期间没有匹配调用”具有意义;只写“没有发现”,却不说明来源、时段、保留率、时钟和缺口,价值很低。如果应用日志遗漏工具编号,或远端日志不保存参数,要明确这会怎样影响轮换与通知决策。
可以用一套简单信心等级统一沟通:“确认请求”需要编号与账号对应;“确认解析”再增加调用集合或发现证据;“确认调用”再增加应用或远端调用记录;“确认影响”还要有被访问对象、返回数据或状态变化。标为“可能”时必须写出缺失环节。这样,法务、隐私、工程和服务负责人能共享一条时间线,又不会把每个脆弱请求都写成已入侵。
7.2 响应既要移除脆弱代码,也要缩小保存身份的权限并留下可验证记录
- 证明服务构建。记录每个副本、摘要、修订、进程启动时间及处理聊天补全的路由。
- 升级并重启。把全部 worker 升至 Open WebUI 0.8.6 或更高版本,在交付包上验证本地和 MCP 拒绝跟踪。
- 盘点能力。把每项本地函数和远端方法映射到所有者、授权、凭据、目的地、数据等级和写权限。
- 保存历史。导出聊天元数据、请求与代理日志、工具修订、授权、组、连接配置和远端审计。
- 逐对象还原。从编号请求一路分级到解析、模型选择、调用、响应与下游影响。
- 控制身份。撤销暴露或可能暴露的会话或账号;已经观察使用或无法限定范围时轮换连接凭据,并检查下游变化。
- 减少常驻权限。拆分读写连接,缩小令牌和方法集合,限制出站访问,把高影响工具只授予明确小组。
- 保留验收证据。保存回归跟踪、迁移结果、最终摘要、重启证明以及允许与拒绝样本。
恢复后,把权限判断作为一等安全事件持续监控。事件应包含请求者、资源编号与类型、所有者、相关组、授权来源、结果、原因、服务修订和关联编号。对重复拒绝选择,以及高影响连接突然被共享或开放的情况进行告警。消息正文可独立管理,避免隐私政策迫使团队丢掉权限遥测。
响应只有在四个问题都能用证据回答时才算闭合:哪些脆弱 worker 服务过流量;当时有哪些受限能力;哪些账号抵达了哪项能力;下游最终使用了哪些身份。升级关闭代码路径,其余答案关闭事件调查。
对外通知、合规报告或客户沟通应使用相同证据分级。受影响版本是产品事实;本组织配置了哪些能力是资产事实;某账号请求、调用或取得数据则是事件事实。把三类事实分开写,既不会因尚无调用证据而隐瞒脆弱性,也不会把“可能访问”误报成“已经泄露”。
调查关闭标准还应写明未解决项。若某个远端系统已经超过日志保留期,就记录无法确认的方法与对象、采取的保守轮换、剩余业务风险和批准人;若证据完整,则保存查询条件与结果摘要。把未知项正式留在结论里,比用一句“未发现异常”盖过去更诚实,也方便以后出现新线索时快速重开。
8 模型可以在能力之间做选择,却不能决定用户拥有哪些能力
CVE-2026-45350 属于 Open WebUI,它留下的设计教训适用于所有给模型装配工具的应用。可调用环境本身就是安全敏感对象。多加入一个函数,可能暴露方法定义、加载代码、读取配置、建立连接、使用凭据或允许写操作。环境必须先由已认证主体和当前策略推导,再序列化给模型。
这也是“让人确认”无法作为通用修复的原因。部分高风险工具可以因产品或安全要求增加确认,但公开复现不需要管理员批准,CVSS 也记录为无需用户交互。若把确认框展示给同一个无权账号,只是让它批准自己原本不拥有的能力。权限判断必须先完成,敏感合法动作才谈得上额外确认。
8.1 每一种新连接器,都应从选择到结果处理守住五项不变量
第一项是服务端选择。客户端可以建议编号、名称或能力,服务器必须自己计算授权子集。页面列表可以改善体验并减少误操作,却不能扩大这个子集。未知与拒绝对象应安全失败,不向客户端泄露私人元数据;内部遥测仍要保留足够细节供调查。
第二项是先判断再使用。授权必须早于模块加载、秘密访问、网络解析、客户端初始化、方法发现、函数注册和执行。这个顺序使拒绝既便宜又可观察,也给回归提供明确目标:结论为拒绝时,所有后续计数都不能移动。
第三项是身份连续。即使实际动作使用服务凭据,每个下游操作也要能追溯到发起用户。关联编号应贯穿补全、发现、工具调用、远端方法与结果。日志同时记录连接主体和用户主体。若远端协议不适合安全携带用户身份,可信应用遥测至少要保存两者映射。
第四项是策略新鲜度。所有权、组、授权、角色和连接设置都可能在对话期间变化。性能缓存不能把已经撤销的工具变成整场会话永久能力。设计需要写清何时重新计算、缓存如何失效、已经开始的远端调用能继续多久。高影响写操作可能还需要临近执行时再次判断。
第五项是结果约束。合法调用仍可能返回敏感数据,生成文件、引用或嵌入内容。调用后还要应用输出分级、对话分享、保留和脱敏规则。这些控制服务于正常工具使用,与本 CVE 缺失的选择检查属于不同问题。分开设计,测试和事故结论都会更清楚。
连接器评审可以把五项不变量写成能力账本。每类资源都列出客户端选择字段、权威记录、策略数据、第一项敏感动作、下游主体、结果通道和审计事件。哪一格为空,哪一处就是代码上线前还没有回答的问题。同一张表可以贯穿威胁建模、实现评审、测试与响应文档。
性能优化也必须保留决策归属。缓存远端定义可以减少重复发现,但只有当前用户先通过权限后,缓存定义才能加入请求;预热连接可以降低延迟,却不能由无权请求触发或继承;批量解析可以减少数据库查询,输出仍需逐对象允许结果。快路径只有在缓存数据、并在约定的新鲜度点重新计算权限时才安全。
8.2 修复后的开场里,私人工具原来出现的位置只剩一条拒绝记录
回到故事开头的普通账号。它发送相同聊天、点名相同私人连接。在固定部署中,中间件取得足以判断权限的连接元数据,发现账号没有匹配授权,写入拒绝并跳过。保存认证没有被读取,MCP 客户端没有打开,远端定义没有进入补全,模型的可调用集合里没有这项服务。
事件响应组成员用匹配组授权发送同样请求,结论则会通过。连接初始化,允许方法被发现,受控调用可以继续。两种结果都必须存在。安全并不是关闭所有工具,而是让每个账号、每次请求得到的调用环境准确符合当时策略。
发布验收要为本地与 MCP 各保存一对跟踪。拒绝本地请求在模块加载前结束,允许请求抵达无害函数;拒绝 MCP 请求在密钥和网络前结束,允许请求抵达受控服务器方法。每条跟踪记录构建摘要、用户、资源、判断原因和时间。
本次公开来源支持的结论,是一个高危认证授权绕过,可能造成高机密性和有限完整性影响。它们没有证明所有部署都能远程执行代码,没有证明可用性损害,没有证明某家企业已经失陷,也没有证明存在野外利用。具体安装是否经历了公告机制之外的后果,只能由本地能力清单和事件证据回答。
证据限制会直接影响沟通方式。漏洞通知可以高信心写出受影响版本、请求路径、缺失判断、连接身份和固定版本;内部事件报告则在日志支持时增加本组织的配置方法、涉及账号、调用与对象。公开说明不能借用从未配置的高权限工具来抬高后果,私下响应也不能因为公告使用了无害 fetch 演示,就忽略自己确实配置的强大工具。
如果团队现在才开始,最短的负责路径依旧具体:把全部 worker 升到 0.8.6 或更高版本;在运行包上验证两条检查;盘点本地工具、MCP 连接、保存身份和授权;保留历史请求与策略;关联远端审计;在已观察使用或无法限定时轮换凭据;恢复后继续记录逐对象授权。
对维护者来说,最持久的产物是一条执行顺序。身份随请求到达,策略针对每个对象计算;只有允许资源可以加载代码、公开定义、读取凭据、建立连接或执行;结果再进入自己的数据控制。以后即使增加新工具协议和新界面,这个顺序也不需要改变。
最初的矛盾——菜单里私人、服务器里可用——会在服务器成为权威后消失。菜单和请求仍可能不同,因为客户端可以发送任意内容;可调用集合不再跟随客户端的主张,只跟随账号真正拥有的权限。只有这一种“可用”,才可以安全地交给模型。
最终状态是可测量的:请求可以写入任意字符串;解析器输出的每个成员都有允许原因;每次凭据读取与工具执行都能回指一项决策;拒绝对象只留下拒绝事件,不产生敏感副作用。当这些话在本地工具、MCP 连接、副本、迁移和撤销场景中都成立,开头那只私人柜子才真正锁在了运行中的服务器上。
研究记录
9证据、对象与来源
下面保留本文实际使用的标识、时间和原始材料,便于继续调查。
9.1研究对象
报告涉及的产品、行为者、技术、受影响对象和控制点。
Open WebUI 聊天补全受限工具授权绕过
项目公告列出的受影响范围
项目建议的完整固定底线
携带工具选择的已认证聊天补全路由
本地工具所有者、组与读取权限判断
v0.8.6 MCP 路径使用的连接访问判断
9.2事件时间
- 私下提交报告
GitHub Security Lab 记录问题通过项目漏洞报告流程提交。
- v0.7.0 发布
项目公告指出的本地工具记录首次固定版本发布。
- v0.8.6 发布
之后被项目公告确认为完整固定底线的版本发布。
- 项目公告公开
协调披露时间线记录 GHSA-4pcg-253r-rf9w 公开。
- GitHub Security Lab 分析公开
GHSL-2026-002 说明请求字段、缺失判断和下游保存身份。
- SOSEC 源码复核完成
受影响源码、两段修复历史、版本证据、响应和回归条件完成核对。
9.3来源与材料
- Open WebUI GHSA-4pcg-253r-rf9w 项目公告https://github.com/open-webui/open-webui/security/advisories/GHSA-4pcg-253r-rf9w
- GitHub Security Lab GHSL-2026-002 技术公告https://securitylab.github.com/advisories/GHSL-2026-002_Open_WebUI/
- CVE-2026-45350 的 CVE Program 记录https://www.cve.org/CVERecord?id=CVE-2026-45350
- Open WebUI 本地工具与服务器访问控制重构https://github.com/open-webui/open-webui/commit/9b06fdc8fe1c933071610336be05f11e77e6c8eb
- Open WebUI v0.8.6 使用的公共连接访问修复https://github.com/open-webui/open-webui/commit/4737e1f11847d057859ec78892fa89e24cbcd83b
- Open WebUI v0.7.0 发布记录https://github.com/open-webui/open-webui/releases/tag/v0.7.0
- Open WebUI v0.8.6 发布记录https://github.com/open-webui/open-webui/releases/tag/v0.8.6
- 受影响 v0.6.43 聊天补全路由https://github.com/open-webui/open-webui/blob/v0.6.43/backend/open_webui/main.py
- 受影响 v0.6.43 补全中间件https://github.com/open-webui/open-webui/blob/v0.6.43/backend/open_webui/utils/middleware.py
- 受影响 v0.6.43 工具解析器https://github.com/open-webui/open-webui/blob/v0.6.43/backend/open_webui/utils/tools.py
- 受影响 v0.6.43 工具记录模型https://github.com/open-webui/open-webui/blob/v0.6.43/backend/open_webui/models/tools.py
- 固定 v0.8.6 补全中间件https://github.com/open-webui/open-webui/blob/v0.8.6/backend/open_webui/utils/middleware.py
- 固定 v0.8.6 本地工具解析器https://github.com/open-webui/open-webui/blob/v0.8.6/backend/open_webui/utils/tools.py
- 固定 v0.8.6 公共访问函数https://github.com/open-webui/open-webui/blob/v0.8.6/backend/open_webui/utils/access_control/__init__.py
- Model Context Protocol 工具规范https://modelcontextprotocol.io/specification/2025-11-25/server/tools
- Model Context Protocol 授权规范https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization
- MITRE CWE-862 缺少授权https://cwe.mitre.org/data/definitions/862.html
- OWASP API1:2023 对象级授权缺陷https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/