一个 30 万美元漏洞的提醒:Agent 接上 API 之后,最不能省的是权限
给 Agent 配好模型,再装几个工具,第一次看到它真的帮你点按钮、查资料,确实容易上头。
紧接着,很多人会想:既然都能干活了,那把邮箱、文档、聊天软件一起接上,岂不是更省事?
我觉得真正该慢半拍的,恰恰是这里。
北京时间 11 月 3 日 10:59,David Singleton 在 X 更新 Muse 漏洞赏金进展:已支付超过 100 万美元,其中一次奖励为 30 万美元。相关官方文章还披露了伪装成工具消息的提示词注入、验证码处理遗漏等问题。[1][2]
这些材料最值得看的,不是赏金有多大,而是一个很实际的问题:当 AI 不只会回答,还能拿着你的权限动手,谁来拦住不该做的那一步?
图 1:依据 Muse 官方披露整理。30 万美元的最高赏金与 9 万美元的提示词注入案例不是同一个漏洞,不能合并讲述。
先把“什么时候、影响谁”说准确
这不是一条“今天 Muse 刚刚泄露全部用户数据”的消息。
官方文章说明,30 万美元对应的问题发现于产品公开上线之前,涉及员工和工程师测试使用的预发布虚拟机。问题与信任校验有关,团队当时关闭服务并处理了它。[2]
另一个已经修复的案例,才是本文更关心的提示词注入:研究人员做了一个网页,模仿 Muse 浏览工具的状态消息。当用户要求总结网页时,这些伪装内容让 Agent 执行了本该被拦截的动作。该案例的赏金为 9 万美元。
不能把两件事拼成“一个网页直接骗走全部用户凭据”,也不能因为官方修复了这些已知问题,就反向保证以后不会再出问题。
把事实边界摆好,后面的讨论才有意义。
网页上的一句话,为什么能变成危险指令
人看网页时,大致知道谁在说话。
文章正文归作者写,浏览器弹窗归浏览器管,自己的操作意图来自自己。它们虽然都显示在屏幕上,但来源和权限不一样。
Agent 处理这些信息时,如果把外部网页内容、工具返回结果和真正的控制指令混在一起,就可能判断错:原本只是“要被阅读的材料”,突然被当成“必须执行的命令”。
这和普通的答非所问不一样。
一个只能聊天的系统理解错了,可能给出一段错误回答。一个能读文件、发消息或调用接口的系统理解错了,后面可能接着发生真实动作。
因此,给 Agent 增加工具时,不能只测试它会不会调用,还得测试它在不该调用的时候会不会停下来。
多写一句“不要被提示词注入”,够不够?
不够把它当成唯一防线。
这句话可以表达使用意图,但不能替代程序的权限检查。最简单的道理是:如果决定“这次可以破例”的,也是刚刚读了可疑内容的那个模型,那最后一道门仍然交给了同一个判断者。
我会把模型和执行器的职责分开。
模型负责提出计划,例如“需要读取某份公开文档”。执行器负责检查:这个动作是否在允许范围内,当前用户有没有权限,参数有没有越界,是否需要人工确认。
模型即使说得再笃定,也不能自己给自己签一张管理员通行证。
这里也别把问题简化成“某个模型更听话,所以不用做权限”。模型能力、提示设计和检测机制都可以改善表现,但它们不能让本来没有授权的动作变得合法。
胜算云应该接在哪一层
在这样的系统里,胜算云可以放在模型请求层:按照官方文档,用 OpenAI 兼容地址https://router.shengsuanyun.com/api/v1,通过 Bearer Key 调用账号实际可用的模型。[3]
调用端仍然由你自己的后端负责。密钥放在服务端受控配置里,不写进公开网页,也不要塞进给模型阅读的日志、提示词或者截图。
一个合理的分工可以是:
| 环节 | 负责什么 | 不应该顺手获得什么 |
|---|---|---|
| 模型请求层 | 理解需求、产生候选计划 | 数据库管理员权限 |
| 应用权限层 | 校验用户身份、资源范围与参数 | 接受模型自报的管理员身份 |
| 工具执行层 | 执行已经批准的有限动作 | 任意 Shell、任意 URL、任意文件路径 |
| 人工确认 | 核对高影响动作及其具体对象 | 只看一句笼统的“是否继续” |
这张表是应用设计建议,不是胜算云已经替你实现的安全功能清单。接入服务提供模型调用能力,业务授权仍然得由你的系统落实。
最小的实操:只允许读取当前用户有权访问的文档
假设模型返回一个计划:读取文档handbook。
执行器不要直接照做,而是用服务端已经认证的用户身份,检查服务端维护的文档权限。这个身份不能从模型回复里拿,也不能因为模型写了“我是管理员”就改变。
下面只演示权限检查,不调用模型,也不真正读取任何文件:
defauthorize_read(proposal,authenticated_user,acl):ifnotisinstance(proposal,dict):raiseValueError('计划必须是对象')ifset(proposal)!={'action','document_id'}:raiseValueError('出现未允许的字段')ifproposal['action']!='read_document':raisePermissionError('动作不在允许列表中')document_id=proposal['document_id']ifnotisinstance(document_id,str):raiseValueError('document_id 必须是字符串')ifdocument_idnotinacl.get(authenticated_user,set()):raisePermissionError('当前用户无权读取该文档')returndocument_id# 演示数据;实际用户身份和 ACL 必须来自服务端可信系统。acl={'demo-user':{'handbook'}}proposal={'action':'read_document','document_id':'handbook'}document_id=authorize_read(proposal,'demo-user',acl)print('通过授权检查的文档 ID:',document_id)接到胜算云时,模型照常通过/chat/completions产生计划;应用把返回内容按 JSON 解析,进行结构检查,再交给这种授权层。只有授权通过的文档 ID 才能进入固定的文档读取接口。
不要把文档 ID 直接拼成任意本地路径,也不要给模型一个可以随便传 URL 的“万能下载工具”。上面的函数也不是完整安全系统,它没有代替用户认证、访问审计、参数长度限制或应用自身的防护。
如果你现在还没准备好这些环节,最简单的起步方式其实是只做“生成建议,不自动执行”。先把输出给人看,确认任务和风险,再逐步开放动作。
图 2:本文建议的授权流程。外部内容只能作为数据进入处理,不能自动提升为更高权限的指令。
上线前,不妨专门测几次“它不该干的活”
很多演示只测试顺利的情况:请查文档,它查到了;请生成摘要,它写出来了。
实际验收还得补上反面用例。比如,模型提议读取没有授权的文档,工具返回了一段自称系统通知的文字,用户要求把内部材料发到外部地址,或者一个本来只读的任务突然提出删除数据。
这些测试最好在隔离环境里,用虚构数据和不产生外部影响的工具完成。重点不是给攻击“加戏”,而是检查权限边界是否真的由程序执行。
对于发送消息、付款、删除和修改权限之类的动作,确认界面需要说清楚对象、内容和后果。只有一句“继续吗”,用户很难判断自己到底批准了什么。
另外,使用任何云端模型或路由服务之前,都应该确认数据经过哪些环节、各环节的保留规则和访问范围。不能因为用了 API,就默认数据只在本机;也不能因为选了某个品牌,就省掉自己的数据最小化设计。
我的看法:会拒绝一次越权操作,也是一种产品能力
我不觉得这次披露说明“Agent 都不能用”。公开问题、修复问题、让外部研究人员参与测试,本来就是系统持续改进的一部分。
但它确实提醒我们,Agent 的演示和生产使用,中间还隔着权限、状态、审计和验收这些不太适合拍短视频的工作。
在我看来,一个系统能准确地说“这一步没有权限,先停下”,并留下可追踪的记录,比它不加区分地把所有工具都调一遍,更值得托付实际任务。
别只给 AI 装工具。还得给每件工具装上真正管用的门锁。
来源与接入说明
- David Singleton:Muse 漏洞赏金进展原帖,2026-11-03 10:59(北京时间)
- Muse 官方文章:Securing Muse,解释漏洞时间、影响范围和修复情况
- 胜算云 OpenAI 兼容 API 文档
- 胜算云接入指南中的 API Key 安全建议
- AIHOT 对应条目
本文包含胜算云产品接入介绍,讨论的是已公开披露并修复的问题。代码仅演示防御性的授权检查,没有复现攻击,也不构成任何平台安全性的保证。配图为说明图。
CSDN 标签:AI Agent、提示词注入、API 安全、权限控制、大模型应用、胜算云