jq${{ github.event.issue.title }}run:Это различие оказалось критичным. GitHub раскрывает выражение до того, как команду начинает выполнять shell. Поэтому вредоносный заголовок с одинарной кавычкой мог закрыть предусмотренную строку и добавить произвольные shell-команды. Последующая обработка значения с помощью sed уже не могла отменить произошедшую ранее интерпретацию shell.
Триггер issues: opened также не делал заголовок доверенным. Любой пользователь, способный открыть Issue в публичном репозитории, мог контролировать его содержимое. Условие, ограничивавшее запуск событиями, связанными с Issues, не препятствовало подстановке данных, которыми управлял атакующий, в shell-команду.
В squash-коммите «Copilot Autofix powered by AI» был указан как соавтор, однако ИИ-проверка не обнаружила проблему. При этом имеющиеся данные не позволяют установить, сгенерировал ли Copilot небезопасное изменение или проверял код, написанный человеком. Корректнее говорить, что Copilot был связан с этим изменением и не выявил внедрение команд, а не утверждать, что авторство модели доказано.
Red Agent сканировал публичную GitHub-организацию Snowflake в поисках опасных шаблонов в CI/CD. Он определил, что workflow Jira передаёт недоверенные данные в shell-блок run:, и сделал вывод: специально сформированный заголовок публичного Issue может привести к выполнению произвольных команд на runner GitHub Actions.
23 июня — через пять дней после слияния уязвимого изменения — агент открыл специально подготовленный Issue в рамках программы Snowflake по поиску уязвимостей на HackerOne. Заголовок вышел за пределы shell-строки, после чего workflow отправил учётные данные Jira на контролируемый внешний callback, использованный для подтверждения концепции атаки.
Это был санкционированный тест безопасности, а не неконтролируемое проникновение. Но сама проблема была реальной: публичный Issue позволял добраться до шага workflow, обрабатывавшего учётные данные, и превратить обычное создание Issue в выполнение команд.
Скомпрометированный workflow имел доступ к настройкам внутреннего Jira Snowflake, включая URL Jira, адрес пользователя и API-токен. Извлечённый токен был связан с учётной записью qa@snowflake.net. Wiz использовала его для входа во внутренний портал Jira и оценки потенциального масштаба доступа.
Согласно сообщениям, токен обеспечивал чтение проектов Jira, связанных с инженерной работой, соответствием требованиям безопасности и активностью bug bounty. Переданные материалы не устанавливают полный набор разрешений токена и не содержат окончательного перечня всех доступных записей. Поэтому наиболее точный вывод состоит в том, что токен позволял получить доступ к чувствительным внутренним данным Jira, но не подтверждает неограниченный доступ к системам Snowflake.
Уязвимым компонентом была CI/CD-автоматизация репозитория. О затронутой выпущенной версии Snowflake Connector for .NET не сообщалось: проблема находилась в workflow GitHub Actions, а не в исполняемом коде самого коннектора.
Wiz сообщила об уязвимости 23 июня. Snowflake исправила workflow в тот же день, а на следующий день сменила раскрытые учётные данные Jira.
Затем Snowflake изучила журналы аудита и пришла к выводу, что в период потенциального доступа единственным действовавшим участником была Wiz. Компания также заявила, что Wiz безопасно удалила данные, полученные в рамках proof of concept.
О несанкционированном доступе третьих лиц, присвоении CVE или затронутом выпуске коннектора не сообщалось. Эти ограничения описывают подтверждённые последствия инцидента, но не делают исходную конструкцию workflow безопасной. Заголовок публичного Issue не должен был становиться частью shell-команды в workflow, работавшем с внутренними учётными данными.
Практический вывод выходит далеко за рамки Snowflake и Copilot. Заголовки Issues и pull request’ов, имена веток и комментарии следует считать потенциально вредоносными данными всякий раз, когда они попадают в shell-команду.
Более безопасная конструкция workflow предполагает:
run:;jq для формирования JSON вместо сборки shell-строк;Этот случай наглядно показывает новую проблему безопасности: одна ИИ-система, помогающая писать и проверять код, может пропустить опасное изменение в CI/CD, а автономный атакующий агент — найти и подтвердить его за несколько дней. Автоматизация ускоряет и исправление, и эксплуатацию уязвимостей, но не заменяет независимую проверку.
jq${{ github.event.issue.title }}run:Это различие оказалось критичным. GitHub раскрывает выражение до того, как команду начинает выполнять shell. Поэтому вредоносный заголовок с одинарной кавычкой мог закрыть предусмотренную строку и добавить произвольные shell-команды. Последующая обработка значения с помощью sed уже не могла отменить произошедшую ранее интерпретацию shell.
Триггер issues: opened также не делал заголовок доверенным. Любой пользователь, способный открыть Issue в публичном репозитории, мог контролировать его содержимое. Условие, ограничивавшее запуск событиями, связанными с Issues, не препятствовало подстановке данных, которыми управлял атакующий, в shell-команду.
В squash-коммите «Copilot Autofix powered by AI» был указан как соавтор, однако ИИ-проверка не обнаружила проблему. При этом имеющиеся данные не позволяют установить, сгенерировал ли Copilot небезопасное изменение или проверял код, написанный человеком. Корректнее говорить, что Copilot был связан с этим изменением и не выявил внедрение команд, а не утверждать, что авторство модели доказано.
Red Agent сканировал публичную GitHub-организацию Snowflake в поисках опасных шаблонов в CI/CD. Он определил, что workflow Jira передаёт недоверенные данные в shell-блок run:, и сделал вывод: специально сформированный заголовок публичного Issue может привести к выполнению произвольных команд на runner GitHub Actions.
23 июня — через пять дней после слияния уязвимого изменения — агент открыл специально подготовленный Issue в рамках программы Snowflake по поиску уязвимостей на HackerOne. Заголовок вышел за пределы shell-строки, после чего workflow отправил учётные данные Jira на контролируемый внешний callback, использованный для подтверждения концепции атаки.
Это был санкционированный тест безопасности, а не неконтролируемое проникновение. Но сама проблема была реальной: публичный Issue позволял добраться до шага workflow, обрабатывавшего учётные данные, и превратить обычное создание Issue в выполнение команд.
Скомпрометированный workflow имел доступ к настройкам внутреннего Jira Snowflake, включая URL Jira, адрес пользователя и API-токен. Извлечённый токен был связан с учётной записью qa@snowflake.net. Wiz использовала его для входа во внутренний портал Jira и оценки потенциального масштаба доступа.
Согласно сообщениям, токен обеспечивал чтение проектов Jira, связанных с инженерной работой, соответствием требованиям безопасности и активностью bug bounty. Переданные материалы не устанавливают полный набор разрешений токена и не содержат окончательного перечня всех доступных записей. Поэтому наиболее точный вывод состоит в том, что токен позволял получить доступ к чувствительным внутренним данным Jira, но не подтверждает неограниченный доступ к системам Snowflake.
Уязвимым компонентом была CI/CD-автоматизация репозитория. О затронутой выпущенной версии Snowflake Connector for .NET не сообщалось: проблема находилась в workflow GitHub Actions, а не в исполняемом коде самого коннектора.
Wiz сообщила об уязвимости 23 июня. Snowflake исправила workflow в тот же день, а на следующий день сменила раскрытые учётные данные Jira.
Затем Snowflake изучила журналы аудита и пришла к выводу, что в период потенциального доступа единственным действовавшим участником была Wiz. Компания также заявила, что Wiz безопасно удалила данные, полученные в рамках proof of concept.
О несанкционированном доступе третьих лиц, присвоении CVE или затронутом выпуске коннектора не сообщалось. Эти ограничения описывают подтверждённые последствия инцидента, но не делают исходную конструкцию workflow безопасной. Заголовок публичного Issue не должен был становиться частью shell-команды в workflow, работавшем с внутренними учётными данными.
Практический вывод выходит далеко за рамки Snowflake и Copilot. Заголовки Issues и pull request’ов, имена веток и комментарии следует считать потенциально вредоносными данными всякий раз, когда они попадают в shell-команду.
Более безопасная конструкция workflow предполагает:
run:;jq для формирования JSON вместо сборки shell-строк;Этот случай наглядно показывает новую проблему безопасности: одна ИИ-система, помогающая писать и проверять код, может пропустить опасное изменение в CI/CD, а автономный атакующий агент — найти и подтвердить его за несколько дней. Автоматизация ускоряет и исправление, и эксплуатацию уязвимостей, но не заменяет независимую проверку.