Uma ilustração abstrata gerada sobre um campo cinza-ardósia escuro: uma longa fita horizontal de linhas finas de luz ciano-pálido e âmbar corre de margem a margem, quebra num ponto preciso perto do centro, e um único fragmento âmbar brilhante escapa para cima, para um canal escuro vazio acima; círculos concêntricos tênues e linhas de grade sugerem um pipeline. Não aparecem texto, pessoas nem logotipos de organizações. O logotipo OrcaRouter está composto no canto inferior direito.
AI Safety Incidents

Token Jira da Snowflake: uma falha que o Copilot coassinou e que, segundo o GitHub, o humano escreveu

Autor

Gideon Frost

Data de publicação

Modelos mais recentes · 20Ver todos os modelos →
Benchmarks: Artificial Analysis · atualizado diariamente
Voltar para todas as publicações

Em 23 de junho de 2026, o Red Agent, um agente de segurança autônomo criado pela Wiz, abriu uma issue em um repositório público do GitHub pertencente à Snowflake e voltou com uma credencial. O repositório era snowflakedb/snowflake-connector-net, e o workflow defeituoso, .github/workflows/jira_issue.yml, existe para abrir um ticket no Jira sempre que alguém abre uma issue — ele montava o título do ticket dentro de um comando shell em vez de passá-lo por uma variável de ambiente, então um título maliciosamente elaborado era executado como código no runner do GitHub Actions. O token que o Red Agent recuperou autenticava-se como qa@snowflake.net contra snowflakecomputing.atlassian.net e dava acesso de leitura aos projetos Jira de engenharia, conformidade de segurança e bug bounty da Snowflake. A falha estava ativa há cinco dias. A Wiz publicou sua análise completa em 17 de agosto de 2026. Este incidente está catalogado como o registro 2026-08-17-snowflake-jira-zhao-dao-can no Orca AI Incident Archive, que contém o conjunto completo de registros com suas classificações de confiança e fontes citadas.

A interpolação, e a guarda que nunca foi executada

O workflow foi acionado no evento do GitHub "issues: opened". Qualquer pessoa com uma conta do GitHub poderia acioná-lo abrindo uma issue em um repositório público — sem convite, sem função de mantenedor, sem fork. A etapa vulnerável lia o título da issue em uma variável de shell: TITLE=$(echo '${{ github.event.issue.title }}' | sed ...), com dois filtros que deveriam escapar aspas duplas e aspas simples antes de a string ser montada.

A falha está na ordem das operações, não no escaping. O GitHub substitui o conteúdo da expressão no texto do script antes mesmo de o bash analisá-lo, de modo que uma aspa simples dentro do título da issue fecha a string entre aspas que o echo mantém aberta. Os dois filtros sed são executados dentro desse mesmo script, depois da substituição, e não conseguem corrigir aspas que já alteraram a forma como a linha é analisada. O relatório da Wiz é explícito ao afirmar que o escaping chega tarde demais para impedir a quebra e que um título elaborado com uma aspa de fechamento e um ponto e vírgula acrescenta comandos à escolha do atacante à etapa de execução.

Um segundo controle deveria restringir o público e não o fez. O job continha uma condição if que comparava github.event.pull_request.user.login com o login do bot whitesource-for-github-com, evidentemente para impedir que pull requests automatizados de dependências abrissem tickets. Em um evento issues, não existe nenhum objeto pull request, então a comparação é feita com uma propriedade nula. A própria documentação do GitHub, citada pelo The Hacker News, afirma que a desreferência de uma propriedade inexistente é avaliada como uma string vazia; a análise da Wiz chega ao mesmo resultado por meio do valor nulo. De qualquer forma, a condição era avaliada como verdadeira para todos os usuários, e a exceção para o bot tornou-se uma passagem direta para a internet.

O que tornou a injeção digna de ser relatada, em vez de rotineira, foi o contexto em que ocorreu. A mesma etapa mantinha JIRA_BASE_URL, JIRA_USER_EMAIL e JIRA_API_TOKEN como variáveis de ambiente, de modo que a execução arbitrária de comandos no runner tinha uma credencial ao alcance, e não um substrato vazio. Nenhuma versão do Snowflake Connector for .NET foi identificada como afetada: a fraqueza estava na automação de CI/CD do repositório, não no código do conector distribuído.

O que o Red Agent levou, e o que diz que jogou fora

O relato da exploração feito pela Wiz é a parte que diferencia isso de uma descoberta de scanner. O primeiro payload usou um caractere hash, que comentou o parêntese de fechamento da atribuição TITLE=$(...) e produziu um erro de sintaxe do bash em vez de um callback. O agente leu o erro e reescreveu o payload para fechar o bloco de shell com um ponto e vírgula e uma nova aspa de echo, e então recebeu uma chamada fora de banda. O payload usou curl para alcançar um subdomínio de oast.me com valores codificados em base64 das três variáveis de credenciais, e o callback chegou do IP da Azure 20.106.182.197, um endereço que a Wiz atribui a um runner do GitHub Actions.

O token retornado era um token da API do Jira para qa@snowflake.net, e a Wiz descreve seu alcance como acesso de leitura que abrange os projetos de engenharia, conformidade de segurança e acompanhamento de bug bounty na instância da Atlassian cloud da Snowflake. Esse é o dano que o arquivo registra: não execução de código em uma máquina de build por cinco dias, mas uma credencial capaz de ler as filas de tickets onde bugs de engenharia e segurança ainda não corrigidos são registrados — incluindo, conforme a descrição da Wiz, o rastreador de bug bounty.

A self-built HTML card titled 'What the run step could reach', badged 'snowflakedb/snowflake-connector-net · .github/workflows/jira_issue.yml · 18-23 June 2026'. A left panel lists the environment variables held by the step: JIRA_BASE_URL, JIRA_USER_EMAIL, JIRA_API_TOKEN. A right panel reads: identity qa@snowflake.net; Jira host snowflakecomputing.atlassian.net; access, read across engineering, security-compliance and bug-bounty Jira projects. Three tiles read: trigger 'issues: opened'; account required 'any GitHub user'; token rotated '24 June 2026'. A footer cites Wiz Research, published 17 August 2026, and notes no CVE identifier accompanies the flaw.

A Wiz afirma que excluiu com segurança tudo o que acessou durante a prova de conceito. A Snowflake, em comunicado ao CSO Online, disse que o relatório "foi imediatamente investigado e corrigido" e que "nossa investigação não encontrou evidências de acesso não autorizado"; o blog da Wiz acrescenta que a Snowflake revisou os logs de auditoria referentes à janela de cinco dias e não encontrou uso por terceiros além dos próprios endereços de teste da Wiz. A Snowflake não publicou esses logs, portanto a conclusão de que nenhum outro ator esteve envolvido se baseia em seu relato e no resumo feito pela Wiz sobre ele, e não em documentos que qualquer pessoa fora das duas organizações possa ler.

Quem escreveu a linha vulnerável

Essa pergunta produziu a segunda história, mais extensa. O PR #1218, intitulado "SNOW-2069227: Update jira workflows", foi incorporado por squash em 18 de junho de 2026 como o commit 4a1b8ce, e o commit de squash lista o Copilot Autofix powered by AI entre os coautores. A manchete original da Wiz apoiava-se exatamente nisso, descrevendo a falha como estando em um pull request assistido pelo GitHub Copilot, e a cobertura comercial inicial seguiu a mesma linha — a manchete da SC Media dizia "Wiz agent finds Snowflake repo flaw in code co-authored by GitHub Copilot Autofix".

A posição do GitHub, noticiada pelo The Next Web e resumida em uma nota de pesquisa da Cloud Security Alliance, é que sua revisão interna concluiu que "um humano escreveu as contribuições que levaram à vulnerabilidade" e que o Copilot Autofix "não revisou nem contribuiu para elas". A base técnica dessa refutação está no histórico do git. O squash-merge condensa uma pull request em um único commit e carrega adiante todos os trailers de coautoria, independentemente de quais linhas aquele autor alterou, de modo que uma linha de coautor registra a participação na pull request, não a autoria de um hunk específico. O commit com coautoria do Copilot na mesma pull request, 6d0e2fa, alterou jira_close.yml — um workflow diferente do vulnerável jira_issue.yml. A interpolação insegura é atribuída ao commit 094038e, datado de 25 de agosto de 2025 e atribuído pelo GitHub a um engenheiro da Snowflake, sfc-gh-hpathak; o PR #1218 colocou esse padrão no branch padrão em junho de 2026.

A Wiz não retirou a descoberta e mudou o enquadramento no dia da publicação. Seu blog traz uma atualização publicada às 19:57 UTC de 17 de agosto, na qual descreve o Copilot como "um coautor que verificou o PR mesclado e a alteração de código" e que "a identificou como sem qualquer problema", sem perceber as vulnerabilidades, além de admitir que "não está claro se a alteração de código foi assistida por IA". Nesse relato, a falha da IA é de revisão, não de autoria: o pull request mesclado trazia uma coassinatura do Copilot e a injeção sobreviveu a ela. A CSO Online cita o CTO da Wiz, Ami Luttwak, dizendo que a atribuição clara entre humanos e IA "está se tornando um pouco mais difícil de estabelecer", e que "apenas olhar os coautores do PR não é suficiente".

A self-built HTML card titled 'Two accounts of one commit', badged 'PR #1218 · SNOW-2069227 · squash-merged 18 June 2026 as commit 4a1b8ce'. A cyan-headed left panel, 'GitHub, internal review', reads: a human wrote the contributions that led to the vulnerability; Copilot Autofix neither reviewed nor contributed to them; Copilot's co-authored commit 6d0e2fa changed jira_close.yml, not the vulnerable file; the unsafe pattern traces to commit 094038e of 25 August 2025; squash-merging carries each co-author trailer forward regardless of which lines that author touched. An amber-headed right panel, 'Wiz, blog update, 17 August 2026, 19:57 UTC', reads: Copilot was a co-author that checked the merged PR and code change; it identified it as all-clear without noticing the vulnerabilities; it is unclear whether the code-change was AI-assisted; Copilot Autofix is listed among the squash commit's co-authors; the post was revised on the evening of publication without retracting the finding. Below, an open-question strip asks whether Copilot reviewed jira_issue.yml inside PR #1218, and a dashed band lists what is not in dispute.

Vale separar o que os dois relatos têm em comum daquilo que eles contestam. Ambos concordam que o commit squash carrega o trailer de coautoria do Copilot Autofix e que o workflow era explorável. Nenhum dos dois contesta que o GitHub Advanced Security escaneou a revisão final do pull request, extraiu o jira_issue.yml e não sinalizou a injeção — a Wiz relata isso como uma falha de detecção, e a réplica do GitHub diz respeito à autoria, não à varredura. O que permanece sem resolução é se o Copilot revisou as linhas vulneráveis, afinal: a Wiz diz que uma revisão foi executada e as aprovou, o GitHub diz que a ferramenta não teve nenhum papel nelas, e os logs que resolveriam a questão estão com uma das duas empresas. O registro traz os dois relatos em vez de escolher.

Cinco dias, e o que mudou depois

A correção foi rápida assim que o relatório chegou. A Wiz registrou pelo programa HackerOne da Snowflake como relatório #3819931 em 23 de junho e notificou a equipe de segurança da Snowflake pelo Slack no mesmo dia; a Snowflake fez o merge do PR #1402, commit 1dc7766, que substituiu a expansão direta de expressões por variáveis de ambiente passadas ao jq como argumentos. A linha do tempo da Wiz situa a rotação do token do Jira em 24 de junho, e The Hacker News relata a mesma divisão de datas. Já a introdução da própria Wiz diz que a Snowflake remediou a vulnerabilidade e rotacionou a credencial “no mesmo dia” — uma discrepância dentro da fonte primária que o registro não deve encobrir. A correção foi aplicada em 23 de junho; a rotação está datada de 24 de junho na tabela da Wiz.

A divulgação ocorreu no relógio da Snowflake: a Wiz define como prazo de divulgação pública 25 de julho de 2026, trinta dias após uma resolução de 25 de junho sob a política do programa, e publicou a análise em 17 de agosto. A declaração da Snowflake ao CSO Online disse que a empresa "aprecia o relato responsável da Wiz" e que estava trabalhando com a Wiz para compartilhar as lições com o setor. Nem a análise da Wiz nem a reportagem do The Hacker News trazem um identificador CVE, uma pontuação CVSS ou uma entrada no catálogo de exploração conhecida da CISA; a falha era uma configuração de fluxo de trabalho em um repositório público, não uma biblioteca distribuída, então nunca entrou em um banco de dados de vulnerabilidades da maneira usual.

A self-built HTML card titled 'Five days live, five weeks to publication', subtitled 'Every date below is day-precision, as reported by Wiz Research and The Hacker News'. A vertical timeline lists six entries: 25 August 2025, commit 094038e introduces the unsafe jira_issue.yml refactor, attributed by GitHub to a Snowflake engineer; 18 June 2026, PR #1218 squash-merged as 4a1b8ce and the flaw goes live on the default branch; 23 June 2026, Wiz reports via HackerOne #3819931 and Snowflake merges fix PR #1402 as 1dc7766; 24 June 2026, Jira API token rotated, the fix having landed a day earlier; 25 July 2026, public disclosure deadline under Snowflake's HackerOne policy; 17 August 2026, Wiz publishes the full analysis, blog updated at 19:57 UTC. An amber band reads 'Exposure window: five days, 18 to 23 June 2026'. A footer notes no CVE identifier, CVSS score or known-exploited entry accompanies the record.

O que o registro estabelece, e o que não estabelece

O arquivo classifica isto como um achado de pesquisa, e não como um evento de implantação, com severidade alta, nota de confiança A, envolvimento de IA confirmado e dano real registrado; sua data, 17 de agosto de 2026, é o dia em que a Wiz publicou, e o incidente em si abrange 18 a 23 de junho. O núcleo estabelecido é estreito e verificável: um workflow público interpolou texto controlado por atacante em um comando de shell, sua condição de guarda foi comparada a uma propriedade que é nula nesse evento, um token do Jira estava na mesma etapa, um agente autônomo explorou isso, e a Snowflake mesclou uma correção e rotacionou a credencial dentro de um dia.

As partes que são inferência em vez de registro são as que as recontagens casuais tendem a achatar. O Copilot Autofix está documentado como coautor do pull request e não está documentado como autor das linhas vulneráveis; o enquadramento de IA contra IA que dominou o primeiro ciclo de notícias foi retirado em parte pela organização responsável pela reportagem em questão de horas e refutado pelo GitHub. Se a revisão de IA do pull request mesclado examinou jira_issue.yml ainda é uma questão factual em aberto, não uma questão resolvida. E a extensão do acesso, embora descrita em detalhes pela Wiz, não foi auditada de forma independente: nenhuma permissão do Jira, execução de workflow ou registro de auditoria foi tornada pública.

O padrão de correção é aquele que a própria orientação do GitHub vinha recomendando desde julho de 2025 — passar os dados não confiáveis da issue para uma variável de ambiente e entregá-los ao jq como argumento, em vez de expandi-los dentro de um bloco run. O commit mesclado da Snowflake faz exatamente isso, e o tratamento corrigido permanece no branch padrão. Para quem lê o registro como precedente, a conclusão duradoura diz respeito à atribuição, e não à injeção: quando um pull request carrega vários humanos e vários agentes, o trailer de coautoria não consegue dizer quem escreveu uma linha, e tanto a Wiz quanto o GitHub acabaram dizendo isso com palavras diferentes.