资讯动态

wecom-cli 文件沙箱设计完全解析:如何防住符号链接逃逸与凭据文件读取威胁

发布时间:2026/9/30 18:17:48 来源:尧图企业网站定制
wecom-cli 文件沙箱设计完全解析如何防住符号链接逃逸与凭据文件读取威胁【免费下载链接】wecom-cli企业微信开放平台命令行工具 — 让人类和 AI Agent 都能在终端中操作企业微信项目地址: https://gitcode.com/gh_mirrors/we/wecom-cliwecom-cli是企业微信开放平台的命令行工具让人类和 AI Agent 都能在终端中操作企业微信。它的 文件沙箱模块wecom-fscrate是整套安全设计的核心当 AI Agent 替你下载、上传、保存文件时沙箱保证所有读写都越不了界。这篇文章带你完整看懂它是如何防住符号链接逃逸和凭据文件读取这两大威胁的。为什么 CLI 工具需要文件沙箱wecom-cli 的使用场景很特别操作者可能是 AI Agent。Agent 给出的输出路径来自模型推理天然不可信——它可能包含../../越界路径也可能指向~/.ssh/id_rsa这样的凭据文件。沙箱的设计目标就一句话把每一次文件 I/O 都关进一个只有根目录 黑名单两道闸门的空间里。沙箱分三层paths路径解析→policy准入决策→io内核级执行见 sandbox/mod.rs。沙箱三层架构解析、决策、执行层模块职责路径层paths.rs把调用方路径解析为磁盘上的真实物理路径决策层policy/mod.rs黑名单 允许根目录Policy::check是唯一是否放行判定执行层io.rs每个操作一套实现全部走固定根句柄三个关键设计决策读写分离策略读操作和写操作各自持有独立的Policy见 SandboxedFs 结构可以可写当前目录但只读其他目录。Deny 永远优先黑名单即使在无根目录限制的宽松模式下也生效且根目录里包含了被拒绝的条目也不会被重新放行。fail-closed失败即拒绝任何无法映射到允许根的情况一律拒绝而不是放行。防符号链接逃逸先追到真实落点再判定这是沙箱最有价值的对抗点。攻击手法很常见工作目录/link-out → /etc/...沙箱外 工作目录/link-cfg → ~/.config/wecom配置目录黑名单内如果只看路径字符串是否以工作目录开头这类符号链接就能骗过检查。wecom-cli 的解法在 resolve_real_path路径存在 → 用canonicalize跟随所有符号链接拿到真实落点路径尚不存在 → 逐级上溯到最深存在的祖先做canonicalize再拼回剩余尾巴。也就是说判定永远发生在符号链接追到底之后。Policy::check 拿到的real路径若落在允许根之外就返回目标路径超出可访问范围命中黑名单则返回安全策略保护。更妙的是合法符号链接不会误伤链接落在允许根内部比如工作目录内的软链指向同一目录的子目录照常放行。对应端到端测试 003-symlink-escape 覆盖了三组对照场景结果写入真实子目录✅ 放行符号链接落点在根内✅ 放行不误伤符号链接落点在根外 / 黑名单内❌ 拒绝且文件未产生、请求未发出防凭据文件读取形状化黑名单不依赖 $HOME第二个威胁是读取凭据Agent 被诱导把~/.ssh/id_rsa、.env、.aws/credentials当上传源敏感内容就经 API 外泄了。wecom-cli 的答案是内置 deny 表——一组**/…形状的 glob 模式覆盖三类凭据形态凭据目录段**/.ssh、**/.aws、**/.kube、**/.docker、**/.git等凭据文件名**/id_rsa、**/.env、**/.netrc、**/.npmrc、**/.zsh_history等密钥证书扩展名**/*.pem、**/*.key、**/*.p12等。设计上有三个亮点任意深度匹配不绑定家目录。**/.ssh会在路径的任何一层命中所以即使用户伪造了$HOME、把凭据放在别处也照样被拦。见 rule.rs 的 glob 编译与匹配。系统目录前缀拒绝Unix 下/etc、/proc、/sys、/dev、/root通过 recommended_deny_rule 以绝对前缀形式拒绝。读写双方向一致屏蔽黑名单同时作用于读和写——既堵住读凭据外泄也堵住往authorized_keys里持久化、覆盖项目.env投毒这类写侧攻击。大小写折叠比对在 macOS/Windows 上.AWS这类变体会被折叠后命中同一规则见 004 测试用例。端到端测试 004-deny-credential-read 特别验证了伪造$HOME场景把HOME指向含.ssh/id_rsa的临时目录上传该文件直接被安全策略保护拒绝且HTTP 上传请求根本没有发出——内容零泄露。纵深防御还有几道你看不见的闸门除了两大主题沙箱还有多层辅助防线..注入折叠normalize_path 逻辑折叠./..越界的../../escape.json在判定处被拒见 007-dotdot-escape 测试。危险字符筛查chars.rs 拒绝零宽字符、双向控制符可伪造路径看起来像什么及 Windows 备用数据流:写法见 006-dangerous-chars 测试。内核级固定句柄执行层通过 cap-std 根句柄 把每次操作钉死在最长命中根内——检查与操作之间即使有组件被替换也无法逃出句柄。原子写防硬链接劫持atomic_write 发布前检查目标nlink拒绝写入多硬链接目标。临时目录不信任环境变量固定临时目录取值不走TMPDIR/TMP/TEMP防止攻击者用环境变量把允许的根调包。关于硬链接别名的取舍005 测试deny 判定是纯字符串比对硬链接别名按别名自身的字符串路径判定。这是刻意为之的威胁模型收口——防同 UID 本地攻击者不在设计范围内。验证沙箱真的有效e2e 测试套件沙箱不是写了就算项目在 test-e2e/cases/sandbox_paths 下用真实二进制 mock 服务器做了 8 组对抗回归用例验证点001-external-output-confined-to-roots--output只能落在 cwd 或固定临时目录内002-workspace-roots工作区根目录边界003-symlink-escape读/写双侧符号链接逃逸004-deny-credential-read伪造 HOME 下的凭据读取006-dangerous-chars不可见字符注入007-dotdot-escape..注入文件写 目录写双入口008-config-dir-under-cwd-denied即使配置目录在 cwd 内也被 deny一个值得注意的细节测试断言用的是报错特征文本安全策略保护、目标路径超出可访问范围而非具体路径因为 macOS 上/var → /private/var的canonicalize差异会导致路径断言脆弱。总结这套沙箱设计教会我们什么判定必须发生在符号链接追底之后——canonicalize优先、不存在路径按最深祖先回退是防逃逸的第一步paths.rs。黑名单用形状而不是位置——**/.ssh这类任意深度 glob让伪造$HOME毫无意义denylist.rs。Deny 永远赢且读写双向一致屏蔽同时关闭外泄与投毒两条向量policy/mod.rs。执行层用固定根句柄做内核级兜底检查与操作零时差io.rs。威胁模型要写明不防什么——同 UID 本地攻击者不在列硬链接别名按字符串判定是清醒的取舍而非遗漏。对普通用户来说你只需要知道wecom-cli 替你下载、保存、上传的每个文件都经过这套先追底、再比对、后执行的流水线。Agent 说什么沙箱都只信一半。【免费下载链接】wecom-cli企业微信开放平台命令行工具 — 让人类和 AI Agent 都能在终端中操作企业微信项目地址: https://gitcode.com/gh_mirrors/we/wecom-cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑