全文约 2300 字,阅读约 6 分钟。
AI 代码审查放行了自己引入的漏洞。Wiz 安全团队在 2026 年 8 月 17 日披露了这起供应链攻击事件,目标指向 Snowflake 的 Jira 系统。攻击者利用 GitHub Copilot Autofix 生成的一段"修复代码",拿到了访问凭证。对每一个把 AI 提交代码直接合入主干的团队来说,这件事值得认真对待。
一句话说清楚:一个 GitHub Actions 工作流把 issue 标题直接拼进了 shell 命令。攻击者在标题里塞了单引号,就拿到了 Jira 凭证。
根据 Wiz 的技术博客,漏洞位于 snowflakedb/snowflake-connector-net 仓库的 jira_issue.yml 工作流。这个工作流在 issue 创建时触发,把 github.event.issue.title 直接插入到 run 块的 shell 脚本里。
原来的安全写法是通过 env: 变量传递标题,再用 jq 构建 JSON。而 PR #1218 把安全模式删了,换成了直接字符串展开。
关键细节:这个 PR 的 squash commit 把 "Copilot Autofix powered by AI" 列为共同作者。GitHub 的 AI 辅助安全审查对这个改动给出的结论是"all-clear"——没有发现任何问题。
AI 自动修复的代码,由 AI 安全审查放行,最终被 AI 安全研究工具攻破。整条链路里,没有一个人类在关键节点踩刹车。

工作流里有一个看起来像防护的 if: 条件,检查 github.event.pull_request.user.login 是否等于某个 bot 账号。但问题在于:issue 事件里 pull_request 永远是 null。条件变成了 null != 'whitesource-for-github-com[bot]'——永远为真。任何 GitHub 用户都能通过这道门。
Wiz 的 Red Agent 工具构造了一个 issue 标题,在模板展开后跳出 echo 字符串,通过 curl 把 JIRA_API_TOKEN、JIRA_USER_EMAIL 和 JIRA_BASE_URL 以 base64 编码外传到攻击者的监听地址。
被窃取的 token 关联 qa@snowflake.net,拥有 Snowflake 工程、安全合规和漏洞赏金跟踪项目的读取权限。Snowflake 在 2026 年 6 月 23 日当天完成修复并轮换凭证,审计日志确认暴露窗口内没有第三方访问。
Copilot Autofix 把 env: + jq 的安全模式替换成直接插值,大概率是因为后者"看起来更简洁"。但 AI 不理解这个改动在 CI/CD 上下文里的安全含义。它优化了代码,删掉了防线。
Cursor、通义灵码等工具同样具备自动修复和代码补全能力。它们面对 github.event.issue.title 这类不受信输入时,是否理解"不能直接拼进 shell"?这取决于训练数据和上下文窗口,不取决于工具的品牌。

GitHub 的 AI 安全审查对 Copilot Autofix 生成的代码给出了 all-clear。同一个 AI 生态里的生成器和审查器,可能共享相似的盲区。这不是阴谋论——是训练数据分布和评估标准的一致性导致的系统性盲点。
用 AI 生成代码,再用同一个 AI 审查代码,等于让同一个学生给自己批改试卷。
Snowflake 的漏洞从合入到被发现只隔了 5 天。但如果不是 Wiz 的 Red Agent 主动扫描,这个后门可能存活更久。问题在于:AI 提交的 PR 如果通过了自动化测试和 AI 审查,有多少团队会再安排人工 review?
现实是,很多团队已经把 AI 提交的代码当成了"低风险"——因为 AI 不会故意写恶意代码。但这次事件证明:AI 不需要恶意,它只需要"无知",就能制造出攻击者梦寐以求的注入点。
Wiz 的 Red Agent 是一个自主 AI 安全研究工具。它扫描 GitHub 组织、发现漏洞、构造 payload、甚至在第一次尝试失败后自主调整了攻击载荷——把 # 注释符改成 ; echo ' 来正确闭合 shell 语法。
攻防双方都在用 AI 加速。防御方用 AI 审查代码,攻击方用 AI 找漏洞。谁的 AI 更懂安全上下文,谁就占上风。

以下清单按优先级排序。每一条都可以在一个工作日内完成初查。
第一,搜 github.event.issue.title 和 github.event.pull_request.title。 在 GitHub Actions 工作流里全局搜索这两个字符串。如果它们出现在 run: 块里而不是 env: 变量里,立即改。这是本次事件的核心漏洞模式,检查成本最低,收益最高。
第二,审查所有 issues: opened 触发的工作流。 这类工作流意味着任何 GitHub 用户都能触发它。检查它们是否处理了不受信输入,以及是否有凭证暴露在运行环境中。
第三,给 AI 生成的 PR 加一道人工确认。 如果团队使用 Copilot Autofix、Cursor 或通义灵码的自动修复功能,建议在合并前增加一条规则:任何涉及 run: 块、凭证处理、输入校验的 AI 改动,必须有人工 review。不需要审查所有 AI 代码,只需要审查高风险区域。
第四,检查 if: 条件里的 pull_request 引用。 在 issue 事件里 github.event.pull_request 永远是 null。任何依赖它做权限判断的逻辑都是无效的。搜索工作流里的 if: 条件,确认它们引用的上下文和触发事件匹配。
第五,给 CI/CD 凭证设置最小权限和短期轮换。 Snowflake 的 Jira token 拥有多个项目的读取权限,这扩大了泄露影响面。建议为 CI/CD 凭证设置最小必要权限,并启用短期轮换。即使泄露,攻击者的窗口也被压缩。
AI 写代码不可怕,可怕的是 AI 写代码、AI 审代码、AI 合代码——整条链路里没有人问一句"这个改动安全吗"。

如果团队满足以下任一条件,建议立即做第一轮自查:使用 GitHub Actions 且仓库公开、工作流处理 issue 或 PR 标题、CI/CD 环境里有生产凭证、AI 提交的代码可以不经人工 review 直接合并。
如果代码仓库完全私有、CI/CD 不暴露任何敏感凭证、AI 工具只用于本地代码补全而不参与提交和审查,那么风险敞口要小得多。但建议至少完成第一条自查——搜索 github.event.issue.title 的成本不到五分钟。
这次事件最值得记住的不是 Snowflake 被攻破,而是攻击链的每一环都有 AI 参与——AI 生成漏洞、AI 放行漏洞、AI 发现漏洞、AI 利用漏洞。工具没有立场,但使用工具的人需要有自己的判断。
你的团队里 AI 提交的代码需要人工 review 吗?评论区留个字母:A.必须人工审 B.AI审完就合 C.还没用AI写代码
#GitHub Copilot #供应链安全 #CI/CD安全 #AI代码审查 #安全自查