最近正在学习智能体安全,目前主要聚焦于两类智能体安全
- 桌面智能体安全
- 企业智能体安全 桌面智能体例如codex、Claude以及各大互联网公司推出的桌面智能体等。
国内某大厂桌面智能体
先来看看国产桌面智能体保护机制 国产的几款测试下来,只在一家智能体上看到了比较完善的沙箱保护。这里不透露具体智能体。
沙箱保护
该智能体默认不启用沙箱。在未开启沙箱时,代码执行默认会直接调用本地终端。
当开启安全保护后,系统会启动一个 VM 虚拟机,同时智能体自身也会修改代码执行逻辑。此时,智能体执行命令时使用的是 mcp:在沙箱开启状态下,mcp 会将命令发送到隔离的 Linux 虚拟机中执行;而在未开启沙箱时,它则会直接在主机上执行命令。
这种机制确实能够有效保护主机安全,使代码执行等高风险操作与主机环境隔离,从而降低被攻击的可能性。但它也存在一些缺点:虚拟机资源通常有限,在运行大型项目时会比较吃力;此外,如果某些软件必须依赖本地环境运行,也会带来额外的不便。
在研究过程中还发现一个有趣的现象:当该智能体运行期间,如果用户临时关闭沙箱,再要求智能体执行代码,系统会报错,并且会强制重新开启沙箱,在沙箱内执行命令。
原因在于,前面提到开启 VM 后,智能体本身的代码执行逻辑已经被修改。即使用户随后关闭沙箱,mcp 的执行逻辑也不会动态切换回主机模式。
Codex
国外的就以codex为例
沙箱保护
codex用的是沙箱+guardian的保护机制。 经常用Codex的都知道,他有几种安全机制:
- 请求批准
- 替我审批
- 完全访问权限 相信大多数人都不会使用请求批准这个模式。这里分析他的guardian机制,就知道为什么这个模式那么难用。
在非“完全访问权限下”所有的动作执行,比如写删文件,网络请求等行为都是经过沙箱的。
请求批准模式
除了读文件,其余发生在工作区外的都要授权
文件写删需要授权
网络访问需要授权
授权之后他会把这次命令拿到沙箱外执行。
替我审批模式(guardian)
直觉上,我们可能以为“替我审批”就是系统默认相信主 Agent,让它自己判断命令是否安全。但从 Codex 的实现看,机制要更细。Codex 并不是让主 Agent 自己给自己放行,而是把原本应该弹给用户的 approval prompt,路由给一个专门的审查子会话。源码里这个角色叫 guardian。
主 Agent 想执行命令、修改文件、访问网络,或者调用需要确认的 MCP 工具时,请求会先经过执行策略层。系统会先判断这个动作属于哪一类:可以直接执行、必须审批,还是直接禁止。只有落到“需要审批”的动作,才会进入自动审批流程。 如果配置是:
approvals_reviewer = "user"
那么需要二次确认的行为会弹给用户。 如果配置是:
approvals_reviewer = "auto_review"
审批请求就不会直接交给用户,而是交给 guardian。 在codex中,其实是有一个专门的codex审批模型,来配合这个审批模式。 guardian 看到的也不是一句简单的“是否允许运行 rm xxx”,而是一份结构化的审批材料:当前任务上下文、用户原始意图、最近工具调用和结果、待执行动作的 JSON 描述,以及相关权限信息。它要判断的不是“这个命令看起来危不危险”,而是:
这个动作在当前任务语境下,是否真的被用户授权?
因此,Codex 的自动审批本质上是一种上下文化授权判断。比如,用户说“帮我跑一下测试”,这通常可以授权构建、测试、写临时文件;但不代表授权删除未提交代码、上传整个工作区,或者修改持久安全配置。guardian 的任务就是判断待执行动作是否仍然落在用户授权范围内。
源码里 guardian 的输出也不是简单的 allow/deny,而是结构化结论,例如 risk_level、user_authorization、outcome 和 rationale。也就是说,它会综合判断风险等级、用户授权强度,最后给出允许或拒绝。
Codex 对 guardian 本身也做了限制。guardian 不是一个拥有更高权限的万能 Agent。它被设置为只读权限,并且 approval_policy = Never。这意味着 guardian 自己不能再申请提权,不能修改文件,也不能通过额外工具扩大行动面。主 Agent 负责执行任务,guardian 负责审查敏感动作,两者不是同一个执行主体。
这个设计本身是合理的,但它也带来一个重要问题:自动审批的效果高度依赖审查模型本身。如果你没有购买codex,而是使用其他模型api,那么在对应的审查模型就无法使用,需要自行替换。
然而我在替换之后发现,非官方模型对于guardian的提示词理解如果有误会造成大量误判。
同时在进行相关研究时,发现了一种攻击手法。
首先刚刚提到过,在非“完全访问权限下”所有的动作执行,都是经过沙箱的。那么即使有一个恶意文件进来了,也是先经过沙箱,在沙箱内发现异常就会阻止或者请求审批。
guardian在审批时,会注入一部分上下文,如果guardian在前面运行该文件时,认为他是一个正常的,后续再运行时,状态发生变化,正常文件变成了恶意文件,guardian被诱导信任该文件,直接通过审批。宿主机就会遭到攻击。我暂时将其命名为“自动审查模式下的延迟语义攻击”,直接提示词注入能通过这种方式绕过沙箱,但间接比较困难,因为目前模型对外部的信息信任度很低,需要多轮间接诱导才行。例如下面的攻击场景。
GPT间接注入案例
假如你正在使用gpt去做网站漏洞挖掘,网站存在一种人机验证,需要你下载他的二进制程序并执行获得签名,在这种场景下,模型可能会存在几种行为
- 先静态分析,分析得到一些字符串,提交后人机验证不通过,再执行
- 不静态分析,直接去运行 在第一种情况下,可以故意将一些字符串不加混淆,让他认为程序不危险,把真正的恶意行为强混淆。最后提权执行就可以执行恶意命令。
测试模型是gpt 5.5 中,测试最后是提权到沙箱外执行,但macos本身有安全策略所以执行失败。

Cursor
沙箱保护
cursor的整体实现和codex类似,本篇文章主要来看他的最新两个漏洞
CVE-2026-50548
Cursor 沙箱的设计大概是:
agent 要运行一个命令
-> Cursor 生成沙箱策略
-> 策略允许命令写入“当前工作目录”
-> 其他地方只读或禁止写
-> 再启动命令
问题在于:“当前工作目录是谁决定的?” 正常情况下应该是 Cursor 自己决定,例如:
workspace = /Users/alice/project
working_directory = /Users/alice/project
于是沙箱策略变成:
允许写:/Users/alice/project
允许写:/tmp
但漏洞逻辑类似这样:
agent 调用 run_terminal_cmd 时可以传 working_directory
Cursor 没有强制检查这个目录必须在 workspace 里
Cursor 直接把 working_directory 加进“允许写”列表
于是被提示注入控制后,agent 可以让工具调用变成:
run_terminal_cmd(
command = "some command",
working_directory = "/Applications/Cursor.app/Contents/Resources/app/resources/helpers"
)
Cursor 看到后可能生成这样的沙箱策略:
允许写:/Users/alice/project
允许写:/tmp
允许写:/Applications/Cursor.app/Contents/Resources/app/resources/helpers
然后
破坏/替换 sandbox helper 或写入启动脚本
后续命令脱离沙箱执行
本机用户权限下 RCE
CVE-2026-50549
假设你的项目目录是:
/Users/alice/project
Cursor 允许 Agent 写这里:
/Users/alice/project/**
现在 workspace 里出现一个 symlink:
/Users/alice/project/out.txt -> /Users/alice/outside-marker.txt
表面路径是:
/Users/alice/project/out.txt
但真实目标是:
/Users/alice/outside-marker.txt
在 workspace 外。 所以安全写入前,Cursor 必须做一件事:
realpath("/Users/alice/project/out.txt")
得到真实目标:
/Users/alice/outside-marker.txt
然后判断:
真实目标是否在 /Users/alice/project 内?
如果不在,就拒绝。
这就是 canonicalization:把路径里的 symlink、..、相对路径等全部解析成真实路径。
漏洞点
漏洞出在解析失败时 正确逻辑应该是:
real = canonicalize(path)
if canonicalize 失败:
拒绝写入
if real 不在 workspace 内:
拒绝写入
写入 real
旧版 Cursor 的问题类似这样:
real = canonicalize(path)
if canonicalize 失败:
real = path # 这里错了
if real 看起来在 workspace 内:
允许写入
也就是说:
/Users/alice/project/out.txt
只要这个“表面路径”在 workspace 内,Cursor 就放行了。可是写文件时,操作系统仍然会跟随 symlink,最后写到 workspace 外部。 为什么 canonicalize 会失败? 常见原因有两个:
- symlink 指向的目标文件还不存在。
- 路径中某个父目录不可读,程序无法解析真实路径。
靶场环境
目前两个CVE的靶场环境已上线ai-vuln-lab