Una ilustración abstracta generada sobre un campo de pizarra oscuro: una larga cinta horizontal de finas líneas de luz cian pálido y ámbar recorre de borde a borde, se interrumpe en un punto preciso cerca del centro y un único fragmento ámbar brillante escapa hacia arriba hacia un canal oscuro vacío por encima; tenues círculos concéntricos y líneas de cuadrícula regladas sugieren un pipeline. No aparecen texto, personas ni logotipos de organizaciones. El logotipo de OrcaRouter está compuesto en la esquina inferior derecha.
AI Safety Incidents

El token de Jira de Snowflake: una falla que Copilot cofirmó, y el humano que GitHub dice que la escribió

Autor

Gideon Frost

Fecha de publicación

Últimos modelos · 20Ver todos los modelos →
Benchmarks: Artificial Analysis · actualizado a diario
Volver a todas las publicaciones

El 23 de junio de 2026, Red Agent, un agente de seguridad autónomo creado por Wiz, abrió una incidencia en un repositorio público de GitHub propiedad de Snowflake y regresó con una credencial. El repositorio era snowflakedb/snowflake-connector-net, y el flujo de trabajo causante, .github/workflows/jira_issue.yml, existe para crear un ticket de Jira cada vez que alguien abre una incidencia; incorporaba el título del ticket en un comando de shell en lugar de pasarlo mediante una variable de entorno, por lo que un título manipulado se ejecutó como código en el runner de GitHub Actions. El token que Red Agent recuperó se autenticó como qa@snowflake.net contra snowflakecomputing.atlassian.net y tenía acceso de lectura a los proyectos de Jira de ingeniería, cumplimiento de seguridad y recompensas por errores de Snowflake. La falla estuvo activa durante cinco días. Wiz publicó su análisis completo el 17 de agosto de 2026. Esta incidencia está catalogada como el registro 2026-08-17-snowflake-jira-zhao-dao-can en el Orca AI Incident Archive, que contiene el conjunto completo de registros con sus grados de confianza y fuentes citadas.

La interpolación, y la guarda que nunca se ejecutó

El flujo de trabajo se activaba con el evento de GitHub «issues: opened». Cualquier persona con una cuenta de GitHub podía dispararlo abriendo una incidencia en un repositorio público: sin invitación, sin rol de mantenedor y sin bifurcación. El paso vulnerable leía el título de la incidencia en una variable de shell: TITLE=$(echo '${{ github.event.issue.title }}' | sed ...), con dos filtros que pretendían escapar las comillas dobles y las comillas simples antes de que se ensamblara la cadena.

El fallo está en el orden de las operaciones, no en el escapado. GitHub sustituye el contenido de la expresión en el texto del script antes de que bash llegue a analizarlo, por lo que una comilla simple dentro del título del issue cierra la cadena entrecomillada que echo mantiene abierta. Los dos filtros sed se ejecutan dentro de ese mismo script, después de la sustitución, y no pueden reparar un entrecomillado que ya ha alterado la forma en que se analiza la línea. El análisis de Wiz es explícito: el escapado llega demasiado tarde para evitar la ruptura, y un título elaborado con una comilla de cierre y un punto y coma añade al paso de ejecución comandos a elección del atacante.

Se suponía que un segundo control restringiría la audiencia, pero no lo hizo. El trabajo contenía una condición if que comparaba github.event.pull_request.user.login con el login del bot whitesource-for-github-com, evidentemente para evitar que las solicitudes de extracción automatizadas de dependencias abrieran tickets. En un evento issues no existe ningún objeto de solicitud de extracción, por lo que la comparación se hace contra una propiedad nula. La propia documentación de GitHub, citada por The Hacker News, afirma que desreferenciar una propiedad inexistente da como resultado una cadena vacía; el análisis de Wiz llega al mismo resultado mediante el valor nulo. De cualquier manera, la condición se evaluó como verdadera para todos los usuarios, y la excepción para el bot se convirtió en una vía libre para internet.

Lo que hizo que la inyección mereciera ser reportada en lugar de considerarse rutinaria fue la compañía que tenía. El mismo paso contenía JIRA_BASE_URL, JIRA_USER_EMAIL y JIRA_API_TOKEN como variables de entorno, por lo que la ejecución arbitraria de comandos en el runner tenía una credencial al alcance en lugar de un sustrato vacío. No se identificó ninguna versión de Snowflake Connector for .NET como afectada: la debilidad residía en la automatización CI/CD del repositorio, no en el código del conector distribuido.

Lo que Red Agent se llevó, y lo que dice haber tirado

El relato de Wiz sobre la explotación es la parte que distingue esto de un hallazgo de escáner. La primera carga útil utilizó un carácter de almohadilla, que comentó el paréntesis de cierre de la asignación TITLE=$(...) y produjo un error de sintaxis de bash en lugar de una llamada de retorno. El agente leyó el error y reescribió la carga útil para cerrar el bloque de shell con un punto y coma y una nueva comilla de echo, y luego recibió una llamada fuera de banda. La carga útil utilizó curl para alcanzar un subdominio de oast.me con valores codificados en base64 de las tres variables de credenciales, y la llamada de retorno llegó desde la IP de Azure 20.106.182.197, una dirección que Wiz atribuye a un runner de GitHub Actions.

El token que devolvió era un token de API de Jira para qa@snowflake.net, y Wiz describe su alcance como acceso de lectura que abarca los proyectos de seguimiento de ingeniería, cumplimiento de seguridad y bug bounty en la instancia de Atlassian Cloud de Snowflake. Ese es el daño que registra el archivo: no la ejecución de código en una máquina de compilación durante cinco días, sino una credencial que podía leer las colas de tickets donde se registran errores de ingeniería y seguridad sin corregir — incluido, según la descripción de Wiz, el 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.

Wiz afirma que eliminó de forma segura todo aquello a lo que accedió durante la prueba de concepto. Snowflake, en un comunicado enviado a CSO Online, declaró que el informe «se investigó y se remedió de inmediato» y que «nuestra investigación no encontró pruebas de acceso no autorizado»; el blog de Wiz añade que Snowflake revisó los registros de auditoría del periodo de cinco días y no halló ningún uso por parte de terceros más allá de las propias direcciones de prueba de Wiz. Snowflake no ha publicado esos registros, por lo que la conclusión de que no intervino ningún otro actor se basa en su versión y en el resumen que de ella hace Wiz, y no en documentos que alguien ajeno a las dos organizaciones pueda leer.

¿Quién escribió la línea vulnerable?

Esa pregunta produjo la segunda historia, más extensa. La PR #1218, titulada «SNOW-2069227: Update jira workflows», se fusionó mediante squash el 18 de junio de 2026 como el commit 4a1b8ce, y el commit de squash incluye a Copilot Autofix powered by AI entre sus coautores. El titular original de Wiz se apoyó exactamente en eso, describiendo la falla como presente en una pull request asistida por GitHub Copilot, y la cobertura inicial de la prensa especializada siguió la misma línea; el titular de SC Media rezaba: «El agente de Wiz encuentra una falla en el repositorio de Snowflake en código coescrito por GitHub Copilot Autofix».

La postura de GitHub, informada por The Next Web y resumida en una nota de investigación de Cloud Security Alliance, es que su revisión interna encontró que «un humano escribió las contribuciones que llevaron a la vulnerabilidad» y que Copilot Autofix «no las revisó ni contribuyó a ellas». La base técnica de esa refutación está en el historial de git. La fusión por squash colapsa una pull request en un único commit y arrastra cada trailer de coautor hacia adelante independientemente de qué líneas tocó ese autor, por lo que una línea de coautor registra la participación en la pull request, no la autoría de un fragmento concreto. El commit con coautoría de Copilot en la misma pull request, 6d0e2fa, modificó jira_close.yml, un flujo de trabajo diferente del vulnerable jira_issue.yml. La interpolación insegura se atribuye al commit 094038e, fechado el 25 de agosto de 2025 y atribuido por GitHub a un ingeniero de Snowflake, sfc-gh-hpathak; la PR #1218 llevó ese patrón a la rama principal en junio de 2026.

Wiz no retiró el hallazgo, y cambió el enfoque el día de la publicación. Su blog contiene una actualización publicada a las 19:57 UTC del 17 de agosto que describe a Copilot como «un coautor que revisó el PR fusionado y el cambio de código», el cual «lo identificó como sin problemas» sin advertir las vulnerabilidades, y admite que «no está claro si el cambio de código contó con asistencia de IA». En esa versión, el fallo de la IA es de revisión, no de autoría: la solicitud de extracción fusionada llevaba una cosignatura de Copilot y la inyección sobrevivió a ella. CSO Online cita al CTO de Wiz, Ami Luttwak, quien afirma que la atribución clara entre humanos e IA «se está volviendo un poco más difícil de establecer», y que «no basta con mirar solo a los coautores del PR».

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.

Lo que ambas versiones comparten merece separarse de aquello que disputan. Ambos coinciden en que el commit de squash incluye el trailer de coautoría de Copilot Autofix y en que el flujo de trabajo era explotable. Ninguno de los dos niega que GitHub Advanced Security escaneó la revisión final del pull request, extrajo jira_issue.yml y no marcó la inyección: Wiz lo reporta como una omisión, y la réplica de GitHub gira en torno a la autoría y no al escaneo. Lo que sigue sin resolverse es si Copilot revisó siquiera las líneas vulnerables: Wiz afirma que se ejecutó una revisión y que las aprobó, GitHub sostiene que la herramienta no intervino en ellas, y los registros que lo dirimirían obran en poder de una de las dos empresas. El registro recoge ambas versiones en lugar de decantarse por una.

Cinco días, y qué cambió después

La reparación fue rápida una vez que llegó el informe. Wiz lo presentó a través del programa HackerOne de Snowflake como informe n.º 3819931 el 23 de junio y notificó al equipo de seguridad de Snowflake por Slack ese mismo día; Snowflake fusionó el PR n.º 1402, commit 1dc7766, que sustituyó la expansión directa de expresiones por variables de entorno pasadas a jq como argumentos. La cronología de Wiz sitúa la rotación del token de Jira el 24 de junio, y The Hacker News informa la misma divergencia. La introducción de Wiz, en cambio, afirma que Snowflake remedió la vulnerabilidad y rotó la credencial "el mismo día", una discrepancia dentro de la fuente primaria que el registro no debería disimular. La corrección se aplicó el 23 de junio; la rotación figura con fecha del 24 de junio en la tabla de Wiz.

La divulgación se rigió por el calendario de Snowflake: Wiz fija la fecha límite de divulgación pública para el 25 de julio de 2026, treinta días después de una resolución del 25 de junio conforme a la política del programa, y publicó el análisis el 17 de agosto. La declaración de Snowflake a CSO Online decía que la empresa «agradece la divulgación responsable de Wiz» y que estaba trabajando con Wiz para compartir las lecciones con la industria. Ni el análisis de Wiz ni el informe de The Hacker News contienen un identificador CVE, una puntuación CVSS ni una entrada en el catálogo de vulnerabilidades explotadas conocidas de CISA; la falla era una configuración de flujo de trabajo en un repositorio público, no una biblioteca distribuida, por lo que nunca entró en una base de datos de vulnerabilidades de la manera habitual.

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.

Lo que el expediente establece, y lo que no

El archivo lo clasifica como un hallazgo de investigación en lugar de un evento de despliegue, con severidad alta, una calificación de confianza A, participación de IA confirmada y daño real registrado; su fecha, 17 de agosto de 2026, es el día en que Wiz lo publicó, y el incidente en sí abarca del 18 al 23 de junio. El núcleo establecido es acotado y verificable: un flujo de trabajo público interpoló texto controlado por el atacante en un comando de shell, su condición de guarda se comparó con una propiedad que es nula en ese evento, un token de Jira se encontraba en el mismo paso, un agente autónomo lo explotó, y Snowflake fusionó una corrección y rotó la credencial en menos de un día.

Las partes que son inferencia y no registro son las que los relatos informales suelen simplificar. Copilot Autofix está documentado como coautor de la solicitud de extracción y no está documentado como autor de las líneas vulnerables; el enfoque de IA contra IA que dominó el primer ciclo de noticias fue retractado en parte por el medio que lo publicó en cuestión de horas y refutado por GitHub. Que la revisión de IA de la solicitud de extracción fusionada haya examinado jira_issue.yml sigue siendo una cuestión fáctica abierta, no resuelta. Y el alcance del acceso, aunque Wiz lo describió en detalle, no ha sido auditado de forma independiente: no se ha hecho público ningún permiso de Jira, ejecución de flujo de trabajo ni registro de auditoría.

El patrón de corrección es el que la propia guía de GitHub venía recomendando desde julio de 2025: pasar los datos no confiables de incidencias a una variable de entorno y entregárselos a jq como argumento, en lugar de expandirlos dentro de un bloque de ejecución. El commit fusionado de Snowflake hace exactamente eso, y el manejo corregido permanece en la rama predeterminada. Para cualquiera que lea el registro como precedente, la conclusión duradera tiene que ver con la atribución y no con la inyección: cuando una pull request incluye a varias personas y varios agentes, el trailer de coautoría no puede decirte quién escribió una línea, y tanto Wiz como GitHub terminaron diciéndolo con distintas palabras.