一个 AI 安全智能体攻进了 Snowflake,Copilot 那条故事反而是噪音
Wiz 的 Red Agent 在 Snowflake 仓库中发现并利用了一个 GitHub Actions 脚本注入漏洞,漏洞上线五天后就完成攻击,全程无人参与。哪些部分真正属于智能体能力,哪些只是普通自动化,以及为什么权限链比作者归属更重要。
本页目录
6 月,一个 AI 智能体攻进了 Snowflake 的内部 Jira,而几乎所有人最先写进标题的,恰恰是最不重要的部分。最初版本的故事说,漏洞代码是 GitHub Copilot 写的,于是很顺手地变成了一则“AI 污染 AI”的寓言。但这个版本只活了几个小时。Wiz 当天就修正了自己的披露,GitHub 也明确否认这种归属。修正后留下来的故事反而更奇怪,也更有价值:一个自主智能体发现线上真实漏洞,自己写利用代码,调试失败的攻击载荷,最后取出可用凭据,从头到尾没有人类介入,而扫描同一份代码的传统安全工具什么都没发现。这才是值得花时间看的故事。
关键要点 - Wiz 的 Red Agent 是一个自主攻击安全智能体。它在 Snowflake 公开的 snowflake-connector-net 仓库里发现 GitHub Actions 工作流存在脚本注入,并成功利用漏洞窃取 Jira token。从发现到凭据外传之间,没有任何人碰键盘。 - 漏洞于 2026 年 6 月 18 日上线,6 月 23 日被发现、利用并报告,全程发生在 Snowflake 的 HackerOne 漏洞奖励计划范围内。Snowflake 当天修复,审计日志显示五天暴露窗口里只有 Wiz 进行过访问。 - 最初“Copilot 写了这个漏洞”的说法在几小时内被撤回。存在漏洞的模式来自人工编写的改动;Copilot Autofix 有记录的贡献发生在另一个文件,而共同作者标签只是 squash merge 带来的元数据产物。 - GitHub Advanced Security 扫描过漏洞存在的准确版本,却没有发现问题。模式匹配扫描器和智能体看的是同一份代码,只有后者理解了它。 - 真正属于智能体的部分范围很窄,但确实存在:它诊断了一次失败的利用尝试,然后重写攻击载荷。其余部分更接近把语言模型放进优秀自动化流程里。
发生了什么
下面的时间线都来自 Wiz 的披露以及 Snowflake 对事件的回应:
2026 年 6 月 18 日。 PR #1218 合并到 snowflakedb/snowflake-connector-net,也就是 Snowflake 公开的 .NET 连接器仓库。PR 重写了一个名为
jira_issue.yml的工作流,它会在有人创建 GitHub issue 时自动新建 Jira 工单。重写前使用的是安全模式:把 issue 标题先通过环境变量传给jq --arg。重写后则直接把标题插值进 shellrun:块。6 月 23 日。 Wiz 的自主安全研究智能体 Red Agent 在 Snowflake 的 HackerOne 漏洞奖励计划范围内扫描其 GitHub 组织时,把这个工作流标记为可注入。它构造攻击载荷并执行,第一次因为自己写的 shell 语法错误而失败。随后它诊断错误、重写载荷,第二次成功。一台 Azure 托管的 GitHub Actions runner 向 Wiz 的监听端点回连,发送了 base64 编码的 Jira API token,对应一个服务账户。Wiz 当天通过 HackerOne 报告漏洞。
6 月 23 日,当天。 Snowflake 修复工作流,恢复原来的安全写法。
6 月 24 日。 Jira token 被撤销并轮换。Snowflake 检查审计日志后发现,在五天暴露窗口里除 Wiz 外没有其他访问者。Wiz 表示已经删除概念验证过程中获取的数据。
8 月 17 日。 Wiz 发布由 Wiz Research 威胁暴露负责人 Gal Nagli 撰写的复盘文章,并在当天 19:57 UTC 更新,澄清 Copilot 只是共同作者之一,曾检查合并后的 PR 并给出通过结论,但漏洞改动本身是否有 AI 辅助仍不清楚。
这个 token 对 Snowflake 内部 Jira 具有读取权限,包括工程、安全合规和漏洞奖励计划本身。没有客户数据受到访问,实际发布的连接器也从未受影响。
根据 Wiz Research 的披露,2026 年 6 月 23 日,Wiz 自主 Red Agent 在 Snowflake 的 snowflake-connector-net 仓库中发现并利用 GitHub Actions 工作流的脚本注入漏洞,外传了一个可以读取内部工程、安全合规和漏洞奖励项目的 Jira token。漏洞上线仅五天,全程没有人类参与。Snowflake 当天修复,并通过审计日志确认没有第三方访问。
权限链,一环一环看
这次利用很适合说明 CI 流水线到底在不知不觉中承载了多少信任。顺着一个精心构造的 issue 标题往下看,它最终能触达五层东西:
触发器。 工作流监听
issues: opened,也就是说世界上任何 GitHub 账户都可以通过创建 issue 触发。原本用于限制访问的条件判断,在 issue-opened 事件上始终计算为 true,见技术报道。注入。 新代码执行
TITLE=$(echo '${{ github.event.issue.title }}' | sed ...)。GitHub 会在 shell 运行之前展开${{ }}模板,因此后面的sed转义来得太晚。标题中只需要一个单引号就能关闭字符串,标题剩下的内容就会作为 shell 执行。运行环境。 命令此时运行在 GitHub Actions runner 内,而 runner 按设计就是一台装满凭据的机器。这个 runner 持有一个服务账户的 Jira API token,因为工作流本来的任务就是创建 Jira 工单。
外传。 攻击载荷把 token 进行 base64 编码,再通过带外回调发送到 Wiz 的监听器,因此工作流日志里不会出现明显可疑内容。
最终权限。 token 可以认证进入 Snowflake 内部 Atlassian 环境,并读取工程、安全合规和漏洞奖励等项目。
这条链里的每一环,单独看都是正常、获批、无聊的基础设施:公开仓库、正常工作的工作流、拥有完成任务所需权限的服务账户。漏洞不是某一个单独错误配置,而是这些信任组合在一起以后出现的结果。一个工作流的影响范围,等于其 runner 能触达的一切,而 runner 通常能触达的范围,比编写它的团队记忆中的更广。这和客户问我智能体治理时我给出的论点完全一样:真正该问的从来不是“智能体是什么”,而是“智能体能碰什么”。
这次利用串起了五层合法信任:未认证的 GitHub issue 触发工作流;一个单引号注入逃出 shell 字符串;runner 环境中持有 Jira 服务账户 token;带外回调把 token 外传;最终 token 打开 Snowflake 内部 Jira 的读取权限。GitHub 模板展开先于 shell 转义执行,这就是为什么后面的清理来得太晚,见 Wiz 复盘。
哪些部分真正属于智能体,哪些不是
这里我想说得精确一点,因为“AI 智能体攻进 Snowflake”很容易引向两种偷懒解读:要么它只是一个换了更好营销包装的扫描器,要么就是 Skynet 跑出来了。细节都不支持这两种说法。
带语言模型的普通自动化。 扫描和初步标记属于这一类。Red Agent 的 CI/CD 能力会遍历 GitHub 组织,寻找把不可信输入插值进 run: 块的工作流文件。这是一类早就被充分理解、形态也很好识别的漏洞。把 jira_issue.yml 标出来,是一个优秀静态规则理论上也完全可能做到的事。选择目标、读取工作流、判断是否可利用确实需要能力,但整体仍然接近 Wiz 本来就在销售的持续攻击面管理。
真正属于智能体的部分。 利用循环。智能体第一次攻击载荷使用了一个注释字符,导致 shell 语法被破坏,因此执行失败。它读取 bash 返回的错误,判断为什么自己的载荷格式不对,重写载荷让脚本正确闭合,然后第二次成功。之后它还验证窃取的 token 是否真的能访问 Snowflake Jira,并评估 token 能触达什么范围。能够在自己的攻击里遇到新运行时故障后,无人提示地诊断并适应,这就不再是签名匹配。尝试、观察、纠正这一循环,正是智能体与扫描器之间真正的区别,也是我在更广泛的智能体架构里一直讨论的循环。第一次看到它在无人监督下,攻击性地运行于财富 500 强目标上,确实值得记录。
完全不属于智能体的部分。 范围、伦理和披露。Red Agent 在 Snowflake 的 HackerOne 计划内运行,也就是处于 Wiz 人类员工选择并授权的边界里。自主性是真的,但它有边界、经过授权,也受到监控,而这正是防守方最该注意的点。Wiz 在3 月推出 Red Agent,7 月下旬正式普遍可用,部分能力建立在 Anthropic Claude Opus 上。现在任何安全团队都可以租到这类能力,因此攻击侧的“尝试、观察、纠正”循环很快就会变得非常常见。
Red Agent 的扫描和分诊更接近带语言模型的自动化。真正属于智能体的核心是利用循环:第一次攻击载荷抛出 shell 语法错误后,智能体诊断 bash 失败原因、重写载荷并在第二次成功,之后验证 token 并映射影响范围,全程没有人类帮助,见 Wiz 披露。
Copilot 那一行其实最不重要
最初的标题说 Copilot 写了漏洞,但记录并不支持。Copilot Autofix 在 PR #1218 中有文档记录的贡献,是对另一个文件 jira_close.yml 的单独修复。存在漏洞的插值代码位于一个署名 Snowflake 工程师的提交里,而 GitHub 告诉记者,其内部审查认定 Copilot Autofix 既没有编写、也没有审查这些代码行。合并 PR 上显示的“Copilot 为共同作者”,只是 squash merge 把提交尾部元数据带进来的产物。Wiz 当天就修改文章,The Register 也更正报道。Wiz CTO Ami Luttwak 对 CSO的评论反而抓住真正重点:当每个 PR 都可能有多个智能体参与时,“只看 PR 的共同作者已经不足以判断到底是谁写了什么”。
两件事可以同时成立。第一,根据 Wiz 的叙述,使用 Copilot Autofix 的 GitHub Advanced Security 扫描过该 PR 的最终版本,其中已经包含漏洞工作流,却没有标记注入问题,而且 GitHub 没有否认这一点。第二,声称 Copilot 自己编写了漏洞的具体说法没有依据。AI 辅助审查漏掉了一个关键漏洞,而且它还把那份代码判定为没问题。这本身就是一个关于 AI 审查局限性的真实故事,只不过它不是“AI 写出了漏洞”的故事。把两者混在一起,对任何正在判断自家 PR 到底应该多信任 AI 审查的人都没有帮助。
Wiz 最初暗示 Copilot 参与编写了漏洞代码,但当天就澄清:Copilot Autofix 有记录的贡献发生在同一 PR 的另一个文件里,而共同作者标签只是 squash merge 的产物。GitHub 表示存在问题的重构由人类工程师编写,Copilot 也从未审查那些代码行。没有争议的是:GitHub Advanced Security 扫描了漏洞版本,却什么都没有标记,见 Wiz 更新后的文章和 CSO 报道。
现在可以做什么
如果你的 GitHub Actions 里存放任何秘密,本周就做下面四件事:
在工作流里 grep
run:块中的${{ github.event.* }}。 任何把 issue 标题、PR 标题、分支名或评论正文直接插值进 shell 的做法都可以被注入,没有例外。把值移进env:变量并正确引用,或者通过jq --arg解析。这就是 Snowflake 恢复的安全模式。把 runner 当成凭据存储。 把工作流 token 权限缩到最低,优先使用短生命周期 OIDC 凭据,而不是长期服务账户 token。任何由不可信事件触发的工作流,例如
issues、pull_request_target、评论,都应该按面向互联网的代码来处理。不要让 AI 审查成为最后一道防线。 GitHub 自己的扫描器看过完全同一份代码并给了通过结论。叠加不同检查方式,而且尤其要警惕审查、作者归属和扫描全部委托给同一家厂商模型的工作流。
以后五天暴露窗口都应该被视为太慢。 一个智能体从完全不了解这个仓库,到拿到可用凭据,不到一周。如果你的披露流程仍假设攻击者需要在系统里潜伏几个月,应该更新这个前提。同时准备一套当天就能执行的凭据轮换运行手册,就像 Snowflake 这次做的一样。
常见问题
GitHub Copilot 写了 Snowflake 的漏洞吗?
根据目前证据,没有。Copilot Autofix 的确在合并后的 PR 上显示为共同作者,但它有记录的改动发生在另一个文件,共同作者标签来自 squash merge,而且 GitHub 表示漏洞代码由人类工程师编写。真正成立的是:GitHub Advanced Security 扫描过漏洞版本,却没有发现注入问题。
Wiz 智能体是怎么进入 Snowflake Jira 的?
它发现一个工作流会把 issue 标题直接插值进 shell 脚本。创建一个带有精心构造标题的 issue,就能在 runner 上执行任意命令,而 runner 恰好持有 Jira 服务账户 token。智能体通过带外回调外传 token,再用它读取内部 Jira 项目。Snowflake 在收到报告当天修复工作流,第二天轮换 token。
这算真正的攻击吗?
它是经过授权的攻击。Red Agent 在 Snowflake 的 HackerOne 漏洞奖励计划范围内运行,Wiz 立即披露,Snowflake 审计日志也确认漏洞存续五天内只有 Wiz 访问。没有客户数据被读取。但未经授权的智能体可以完全照着同一种技术执行,这正是这件事值得关注的原因。
这对 AI 安全智能体意味着什么?
意味着攻击型智能体目前跑在防御型自动化前面。一个自主智能体在漏洞发布几天后就发现、利用并确认了真实问题,而看过同一份代码的自动扫描器什么都没发现。防守方应该把“智能体速度的漏洞发现”当成新的基线,并假设任何可以从互联网触发的东西都会以这种速度被探测。
最后的判断
把 Copilot 的戏剧性争论拿掉,只剩两个事实。一个传统、昂贵的安全扫描器审过这份代码,并给了通过结论。一个自主智能体读了同一份代码,理解到足以把它武器化,还能在过程中修正自己的错误。“合并”到“被机器利用”之间只有五天,这才是安全团队应该盯着的数字,因为攻击型智能体现在已经是产品,不再只是研究演示,而且它们不过周末。下个月,大家大概就会忘记 Copilot 到底该不该出现在作者那一行。但这种能力不会消失。
如果你正在决定自己的流水线里,无论攻击侧还是防御侧,应该给智能体多少自主权,这也是我经常和客户讨论的问题。欢迎联系我。
来源
Wiz Research(Gal Nagli),《Wiz Red Agent 通过 GitHub Copilot 辅助 PR 中的漏洞进入 Snowflake 内部 Jira》:https://www.wiz.io/blog/red-agent-snowflake-copilot-cicd-bug (发布于 2026 年 8 月 17 日,更新于 2026 年 8 月 17 日 19:57 UTC,检索于 2026 年 8 月 29 日)
Wiz,《Wiz Red Agent 正式发布:AI 驱动的攻击者》:https://www.wiz.io/blog/introducing-the-wiz-red-agent (发布于 2026 年 3 月 23 日,检索于 2026 年 8 月 29 日)
Cybersecurity News,《AI 智能体攻击 Snowflake GitHub 工作流》:https://cybersecuritynews.com/ai-agent-hacks-snowflake-github-workflow/ (发布于 2026 年 8 月 20 日,检索于 2026 年 8 月 29 日)
CSO Online,《Snowflake 漏洞绕过 AI 检查,又被另一个 AI 利用》:https://www.csoonline.com/article/4211501/snowflake-flaw-slips-past-ai-checks-gets-exploited-by-another-ai.html (发布于 2026 年 8 月 19 日,检索于 2026 年 8 月 29 日)
Infosecurity Magazine,《Wiz AI 智能体发现 Snowflake GitHub 仓库关键漏洞》:https://www.infosecurity-magazine.com/news/wiz-ai-agent-finds-snowflake/ (发布于 2026 年 8 月 18 日,检索于 2026 年 8 月 29 日)
daily.dev,来源 The Next Web,《GitHub 否认 Wiz 关于 Copilot Autofix 编写 Snowflake 漏洞的说法》:https://daily.dev/posts/github-disputes-wiz-s-claim-that-copilot-autofix-wrote-a-snowflake-flaw-ybruxnh95 (发布于 2026 年 8 月 18 日,检索于 2026 年 8 月 29 日)
snowflakedb/snowflake-connector-net 项目仓库:https://github.com/snowflakedb/snowflake-connector-net (检索于 2026 年 8 月 29 日)
继续阅读
Agent Field Notes
获取下一期。
为需要真正运行这些系统的人,解释 Agent Harness、运行时、安全与治理。