工具大全
开发者工具作者:Coocon2026年8月18日229 次阅读约 12 分钟阅读

AI 点头说没问题的代码,5 天后被攻破

AI 点头说没问题的代码,5 天后被攻破

Snowflake 的一个公开仓库,前阵子被人打穿了。攻击者没费多大力气——只是在 GitHub 上开了一个 issue,标题里塞进一行精心构造的字符串。就这样拿到了 Snowflake 内部 Jira 的凭证,工程、安全合规、漏洞赏金三个项目随便看。

而引入这个漏洞的那次代码变更,最后的 squash commit 署名里,躺着一个特殊的"合著者":Copilot Autofix powered by AI。

一个教科书级的 shell 注入,被"顺手"改了出来

Snowflake 的 snowflake-connector-net 仓库里有个工作流 jira_issue.yml,负责把 GitHub issue 同步到 Jira。它原本的写法很稳:把 issue 标题通过 env: 变量传进去,再用 jq 拼 JSON。这是规避注入的标准姿势。

6 月 18 日,PR #1218 把它改成了直接字符串插值——${{ github.event.issue.title }} 直接拼进 shell 脚本,外面包着一层 echo '...'。

学过 shell 的人一眼就能看出问题:标题里放一个单引号,就能跳出 echo 的引号,执行任意命令。

更糟的是,工作流里那个 if: 条件看着像安全闸门,实际上在 issue 事件里 github.event.pull_request 永远是 null,条件恒为真,任何人都能触发。

AI 在流程里出现过两次,两次都没拦住

这件事最值得玩味的,不是"又有一个注入漏洞",而是 AI 在流程里的两个位置。

第一个位置是合入。PR #1218 的 squash commit 署名里,"Copilot Autofix powered by AI" 被列为共同作者。也就是说,这次引入漏洞的改动,Copilot 是挂了名的。

第二个位置是审查。Wiz 在 8 月 17 日更新了博客,澄清了一点:Copilot 是"共同作者",它检查了这个 PR 和代码变更,结论是 all-clear,没发现那个关键漏洞。至于那行代码本身是不是 AI 写的,反而说不清了。

换句话说,不管是 AI 写的还是人写的,AI 这道"审查闸门"都没拦住一个老掉牙的 shell 注入。

另一边,一个 AI 攻击者 5 天就找到了它

Wiz 的安全研究工具 Red Agent,是个自主运行的 AI。它扫 Snowflake 的 GitHub 组织,标记了 jira_issue.yml 的风险,构造 issue 标题,通过外带回调把一个 Jira 账号(qa@snowflake.net)的凭证偷了出来。

有个细节特别耐人寻味:Red Agent 第一次尝试用 # 注释掉后续代码,结果 # 把 TITLE=$(...) 的右括号也吃掉了,触发 bash 语法错误。它没有停下来等人,而是自己分析了报错,把 payload 改成 ; echo ' 正确闭合了 shell,几秒后成功回连。

从漏洞上线(6 月 18 日)到被发现(6 月 23 日),只隔了 5 天。好在 Snowflake 的响应也快:当天就修了漏洞、轮换了凭证,事后确认没有第三方趁虚而入。

一边是 AI 没拦住一个教科书级的注入,一边是 AI 在几天内自主完成发现、调试、利用。这个对比,比漏洞本身更值得警惕。

别急着怪 Copilot,真正的问题在你

把锅全甩给 Copilot 是偷懒。这个漏洞的本质不是"AI 写了坏代码",而是"团队把 AI 的审查当成了安全保证"。

Wiz 自己总结得很到位:AI 编码工具基于概率模式预测代码,可能无意中把已被弃用的不安全写法重新带回来。它缺少"当初为什么用 env:+jq 而不是直接插值"这种历史上下文——那条安全写法存在的意义就是防这类注入,AI 却把它当成了可以"优化"掉的冗余。

所以真正该做的,是把 AI 生成的 diff 当成人写的代码一样审。静态分析、安全扫描、人工复核,一样都不能少。

你今天可以做的三件事

  1. 检查自己仓库里所有 issues: opened 触发的 workflow,看有没有把 ${{ github.event.issue.title }} 或 body 直接拼进 shell。有的话改成 env: + jq。
  2. 给 Copilot/Cursor 的自动修复设一条硬规矩:凡是用字符串拼接替换掉结构化解析(jq、参数化查询)的 diff,一律人工二次确认。
  3. CI 里敏感的 token 换成短时效凭证,GitHub Actions 的 runner 凭证别给读内部系统的权限。

参考来源:

✨ 本文由 DeepSeek 生成初稿,Claude 审核润色。

相关文章

码农早餐 · 2026-10-02

今日头菜:Figma 的 MCP 只认白名单客户端,MCP 作者本人出来说话了。另有 3 条快讯:turbopuffer 把 ANN 降成二级索引:向量数据库真死了吗;从 v0.1.9 到 v0.1.13:TileLang 把 GPU 内核写成了 Python;等。

daily-intel2026年10月2日8 min
29

码农早餐 · 2026-10-01

今日头菜:同一个 prompt,为什么有人做出来像设计师做的。另有 4 条快讯:Pi.dev 从「不接 MCP」到把 MCP 塞进内核;Gemini 4 Argon 定价 2 美元:先给网络安全团队用;等。

daily-intel2026年10月1日9 min
39

码农早餐 · 2026-09-30

今日头菜:Anthropic 招股书:营收翻 12 倍,亏了 420 亿。另有 4 条快讯:0.8B 模型在家训完:254 个选项里选一个,28 毫秒;7 块 ESP32-S3 串成一条链,跑起 0.5B 的 1.58-bit 模型;等。

daily-intel2026年9月30日11 min
67
Claude Code 安装失败实测:npm EACCES、镜像卡 600 秒、Node 20 静默装旧版、install.sh 返回地区拦截页、原生安装器顺手卸掉 npm 版——15 条报错原文与解法

Claude Code 安装失败实测:npm EACCES、镜像卡 600 秒、Node 20 静默装旧版、install.sh 返回地区拦截页、原生安装器顺手卸掉 npm 版——15 条报错原文与解法

在 macOS 上把 claude code 安装的失败面逐个真实复现,共 15 条报错原文,全部带墙钟和 exit code。npm 全局装到 /usr/local:EACCES,exit 243。cache 目录只是 0555,npm 却报 root-owned 并建议 sudo chown。本机 npmmirror 两次分别用了 147 秒、超过 600 秒,官方源两次都在 11–12 秒(仅 2 个样本)。Node 20 不钉版本号会静默装到 2.1.197,没有任何警告。境内直连 claude.ai/install.sh 时 curl exit 0,拿到的却是一张 447KB 的地区拦截页 HTML。原生安装器会调用 npm uninstall -g,把已有的 npm 版删掉,终端里不提示——本次实测真的删掉了本机的全局安装。

claude-codenodejs+6
pitfalls2026年9月29日11 min
95