- Дата публикации
Как Astral защищает свои open source‑инструменты: разбор практик безопасности Ruff, uv и ty
Что нового
Astral подробно раскрыла, как она защищает свои популярные open source‑инструменты — Ruff, uv и ty — от атак на цепочку поставок. Команда не анонсирует один конкретный продукт, а показывает цельную систему защиты, которая включает:
-
Жёстко настроенный CI/CD на GitHub Actions:
- Полный отказ от опасных триггеров
pull_request_targetиworkflow_runво всей организации Astral. - Обязательное пинование всех GitHub Actions до полного SHA‑коммита, включая вложенные действия.
- Автоматические и ручные проверки на «импостер‑коммиты» в сторонних экшенах.
- Максимальное урезание прав workflow по умолчанию (read‑only на уровне организации,
permissions: {}в начале каждого workflow). - Разделение секретов по окружениям, а не на уровне репозитория/организации.
- Полный отказ от опасных триггеров
-
Жёсткие правила для веток и тэгов:
- Организационные правила защиты веток:
mainнельзя форс‑пушить, все изменения только через pull request. - Запрет на создание веток с паттернами
advisory-*иinternal-*, чтобы случайно не слить работу по безопасности. - Тэги релизов появляются только после успешного деплоя релиза и не могут изменяться или удаляться.
- Админы репозиториев не могут обойти эти ограничения — всё зашито на уровне всей организации Astral.
- Организационные правила защиты веток:
-
Вынос опасных автоматизаций из GitHub Actions в GitHub App:
- Для задач вроде комментариев в чужих issue и pull request Astral использует отдельное приложение astral-sh-bot, а не Actions.
- GitHub App получает те же события, что и Actions, но работает в более контролируемой среде.
-
Усиление безопасности релизов и дистрибуции:
- Использование Trusted Publishing для публикации в PyPI, crates.io и npm — без долгоживущих токенов.
- Генерация Sigstore‑аттестаций для бинарников и Docker‑образов, чтобы связать артефакт с конкретным workflow.
- Включённые immutable releases на GitHub — запрет на подмену уже опубликованных билдов.
- Полный отказ от кеширования в релизных workflow, чтобы исключить отравление кеша.
- Релизные workflow вынесены в отдельные окружения с двухфакторным одобрением: нужно минимум два аккаунта с сильной 2FA.
- Для сложных релизов (например, uv) используется дополнительное окружение
release-gateи минимальный GitHub App, который медиирует переход к основному релизному окружению. - Инсталлятор uv проверяет целостность бинарников по чексуммам, зашитым в исходный код установщика.
-
Работа с зависимостями и экосистемой:
- Astral использует Dependabot, Renovate и uv для обновления зависимостей и отслеживания уязвимостей.
- Для сторонних пакетов включены cooldown‑периоды: обновления не ставятся сразу после релиза.
- Команда минимизирует количество зависимостей и особенно избегает бинарных блобов.
- Astral активно контрибьютит в чужие проекты (например, в
apache/opendal-reqsign) и поддерживает их финансово через OSS‑фонд. - Поддерживаются рабочие связи с Python Packaging Authority и Python Security Response Team.
-
Планы на будущее:
- Добавить официальное код‑подписание для macOS и Windows.
- Открыть исходники
astral-sh-bot.
Как это работает
CI/CD на GitHub Actions без «дырявых» триггеров
Astral строит весь основной поток разработки Ruff, uv и ty вокруг GitHub Actions. Это позволяет:
- запускать один и тот же набор проверок для внутренних и внешних pull request;
- держать критические операции (сборка, релиз) внутри контролируемой инфраструктуры, а не на ноутбуках разработчиков.
При этом Astral сознательно отказывается от триггеров, которые трудно сделать безопасными:
pull_request_targetиworkflow_runзапрещены на уровне всей организации;- вместо них используются менее привилегированные триггеры, например
pull_request.
Классический пример: многие проекты включают pull_request_target, чтобы бот мог оставлять комментарии в PR от внешних контрибьюторов. Astral предлагает альтернативы:
- использовать job summary (вывод в интерфейсе Actions);
- или просто логи workflow, если этого достаточно.
Если действительно нужно писать комментарии в чужие PR/issue, Astral предлагает полностью уйти из Actions и использовать GitHub App или вебхук.
Жёсткое пинование GitHub Actions до коммитов
Astral требует, чтобы каждое действие в workflow было привязано к конкретному SHA‑коммиту, а не к тегу или ветке. Причины:
- теги и ветки изменяемы, их можно незаметно перебросить на другой коммит;
- сторонний экшен может быть скомпрометирован через подмену релиза.
Механика защиты:
-
Статический анализ с помощью zizmor:
- правило
unpinned-usesищет незафиксированные экшены; - проверка на impostor‑коммиты — чтобы убедиться, что SHA действительно относится к этому репозиторию.
- правило
-
Политика GitHub “require actions to be pinned to a full-length commit SHA”:
- GitHub откажется запускать workflow, если хоть один экшен (включая вложенные) не привязан к полному SHA.
Чтобы это заработало, Astral договорилась с downstream‑проектами и добилась хеш‑пинования по всей цепочке зависимостей экшенов.
Но этого недостаточно. Даже если экшен сам неизменяем, он может внутри делать изменяемые вещи:
- скачивать «последний релиз» бинарника с GitHub Releases по тегу
latest; - тянуть зависимости без фиксированных версий.
Пока автоматические инструменты плохо находят такие «дыры в неизменяемости», Astral:
- вручную ревьюит действия, от которых зависит;
- помогает авторам экшенов зафиксировать бинарники через маппинг
URL → криптографический хеш, который входит в неизменяемое состояние экшена.
Это не гарантирует подлинность бинарника, но защищает от тихой подмены по изменяемой ссылке.
Минимальные права workflow и изоляция секретов
Astral режет права на всех уровнях:
- на уровне организации GitHub Actions по умолчанию имеют только права на чтение;
- в каждом workflow первая строка —
permissions: {}, а дальше права расширяются по job‑ам, только где нужно.
Секреты тоже изолированы:
- вместо общих секретов репозитория используются deployment environments с отдельными секретами;
- тесты и линтеры не видят секретов, необходимых для публикации релизов.
Это уменьшает «радиус поражения»: если вор прорвётся в один job, он не сможет сразу украсть всё.
Организационная безопасность GitHub
Astral снижает риск компрометации аккаунтов и репозиториев несколькими мерами:
- минимум админов: большинство участников имеют только read/write для нужных репозиториев;
- обязательная сильная 2FA для всех участников (не слабее TOTP);
- план перейти на только фишинг‑устойчивые методы (WebAuthn, Passkeys), когда GitHub позволит.
Правила веток:
mainнельзя форс‑пушить;- все изменения в
main— только через pull request; - запрещены ветки с шаблонами
advisory-*иinternal-*, чтобы не засветить работу над уязвимостями.
Правила тэгов:
- релизный тег нельзя создать, пока не завершится успешный release deployment;
- теги нельзя обновлять или удалять — они становятся неизменяемыми;
- релизный деплой можно запускать только с
main, нельзя обойти правила через боковую ветку.
Ключевой момент: даже админ репозитория не может выключить эти ограничения. Все правила настроены на уровне организации, что сильно повышает планку для атакующего.
Astral поделилась gist с примером своих ruleset‑ов для веток и тэгов — это можно использовать как шаблон для собственных политик.
GitHub Apps вместо опасных workflow
Некоторые задачи GitHub Actions теоретически умеет делать, но безопасно это почти нереально. Типичный пример:
- оставлять комментарии в чужих pull request и issue;
- выполнять автоматические действия от имени репозитория в сторонних контекстах.
Astral решает это через GitHub App astral-sh-bot:
- GitHub отправляет приложению те же webhook‑события, что и Actions;
- код приложения работает в отдельной инфраструктуре, где нет такого плотного смешения кода и данных, как в Actions.
GitHub App всё равно хранит чувствительные креденшалы, поэтому Astral подчёркивает:
- разработка GitHub App — это обычная разработка со всеми рисками: SQL‑инъекции, prompt‑инъекции, ошибки авторизации;
- приложение не делает запуск недоверенного кода безопасным, оно лишь снижает шанс, что вы выполните его неожиданно.
Если вам нужно запускать недоверенный код (например, тесты для внешнего PR), используйте только «безопасные» триггеры, вроде pull_request, которые не выдают привилегированные секреты коду из форков.
Astral использует фреймворк Gidgethub для разработки GitHub Apps на Python и рекомендует туториал Mariatta как хорошую точку входа. Хостинг остаётся узким местом: нужно своё окружение, время и деньги.
Что это значит для вас
Если вы поддерживаете open source‑проект
Из опыта Astral можно сразу забрать несколько практик:
-
Отключите опасные триггеры:
- запретите
pull_request_targetиworkflow_run, если вы не уверены на 100%, что понимаете их последствия; - для комментариев в PR используйте job summary или отдельный GitHub App.
- запретите
-
Пините GitHub Actions по SHA:
- в каждом
uses:указывайте полный SHA‑коммит; - включите организационную политику GitHub «require actions to be pinned to a full-length commit SHA»;
- используйте zizmor или аналог для поиска незафиксированных экшенов.
- в каждом
-
Ограничьте права workflow:
- настройте read‑only по умолчанию на уровне организации;
- начинайте каждый workflow с
permissions: {}; - выдавайте права на запись только тем job, которым это реально нужно.
-
Разнесите секреты по окружениям:
- создайте отдельные environments для релизов, тестов, staging;
- храните токены публикации только в релизном окружении;
- включите ручное одобрение для запуска релизного окружения.
-
Укрепите релизы:
- используйте Trusted Publishing для PyPI / crates.io / npm, если можете;
- включите immutable releases на GitHub;
- запретите обновление/удаление релизных тэгов;
- по возможности генерируйте Sigstore‑аттестации для бинарников и Docker‑образов.
-
Работайте с зависимостями осознанно:
- подключите Dependabot или Renovate;
- настройте cooldown‑периоды для сторонних пакетов;
- минимизируйте количество зависимостей и особенно бинарных блобов.
Если вы используете Ruff, uv или ty
Для вас эти меры означают:
- меньший шанс, что вы скачаете скомпрометированный релиз через PyPI, Homebrew или Docker;
- меньше риск, что кто‑то подменит уже опубликованный релиз на GitHub;
- повышенную прозрачность происхождения артефактов через Sigstore‑аттестации;
- более надёжные релизные процессы, которые сложнее сломать через компрометированный аккаунт.
Если вы ставите uv через standalone‑инсталлятор, он проверяет бинарники по чексуммам, встроенным в исходный код инсталлятора. Это не защищает от всех сценариев атаки, но сильно осложняет тихую подмену бинарника на пути доставки.
Где это не поможет
Эти практики не решают, например:
- уязвимости в самом коде инструментов Ruff, uv или ty;
- проблемы в вашей собственной инфраструктуре CI/CD;
- злонамеренные изменения от доверенного мейнтейнера.
Astral честно говорит: защита — это набор постоянно меняющихся техник, а не раз и навсегда закрытый вопрос. Команда планирует продолжать усиливать свои процессы.
Доступность из России
Ruff, uv и ty — open source‑инструменты, код и релизы находятся на GitHub и PyPI. Для доступа к GitHub, PyPI, crates.io, npm и Sigstore‑инфраструктуре в некоторых сетях может понадобиться VPN. Конкретные ограничения зависят от вашего провайдера и корпоративной политики.
Место на рынке
Astral не выпускает новую LLM, а укрепляет инфраструктуру вокруг уже широко используемых инструментов:
- Ruff — один из самых популярных и быстрых линтеров/форматеров для Python;
- uv — менеджер пакетов и виртуальных окружений, который позиционируют как более быстрый и надёжный аналог существующих решений;
- ty — ещё один инструмент в экосистеме Astral.
На рынке безопасности open source‑цепочек поставок у Astral несколько ближайших «игроков по духу»:
- проекты, которые жёстко пинят зависимости и экшены (часть крупных OSS‑организаций уже так делает);
- инициативы вокруг Sigstore и воспроизводимых сборок;
- Trusted Publishing, который активно продвигает PyPI.
Конкретных чисел сравнения по скорости, стоимости или проценту предотвращённых атак Astral не приводит. Но по объёму и глубине описанных практик видно, что команда строит защиту на уровне крупных экосистемных проектов: от настроек организации GitHub до тонкой работы с зависимостями и сообществом.
Если вы разрабатываете инструменты, от которых зависят тысячи или миллионы разработчиков, подход Astral — хороший ориентир по уровню паранойи и качеству процессов, к которому стоит стремиться.
Как запустить подобную защиту у себя
Ниже — практический чек‑лист, который можно адаптировать под свой проект.
1. Политики GitHub Actions
-
На уровне организации:
- отключите
pull_request_targetиworkflow_runв разрешённых триггерах; - включите политику require actions to be pinned to a full-length commit SHA;
- установите права по умолчанию read‑only для workflow.
- отключите
-
В каждом репозитории:
- добавьте в начало всех workflow:
permissions: {}
- явно задавайте права для каждого job, например:
jobs:
tests:
permissions:
contents: read
release:
permissions:
contents: write
id-token: write
2. Пинование экшенов
- Пройдитесь по всем
uses:и замените теги на SHA:
- uses: actions/checkout@v4
# заменить на
- uses: actions/checkout@<full_sha>
-
Подключите zizmor или аналог для поиска непинованных экшенов и impostor‑коммитов.
-
Свяжитесь с авторами сторонних экшенов, если они тянут непинованные бинарники или зависимости.
3. Environments и релизы
-
Создайте окружения:
test,staging,release, возможноrelease-gate.
-
В
release:- храните только релизные секреты (токены для PyPI, Docker Registry и т.п.);
- включите обязательное ручное одобрение минимум одним человеком с нужными правами.
-
Настройте правила веток и тэгов:
- запретите force‑push в
main; - запретите прямые пуши в
main, только через pull request; - запретите обновление и удаление релизных тэгов;
- разрешите создание релизных тэгов только после успешного релизного деплоя.
- запретите force‑push в
-
Включите immutable releases на GitHub, чтобы нельзя было переписать уже опубликованный релиз.
4. Trusted Publishing и Sigstore
-
Если вы публикуете пакеты в PyPI, crates.io, npm:
- настройте Trusted Publishing или другой OIDC‑флоу, чтобы уйти от долгоживущих токенов.
-
Для бинарников и Docker‑образов:
- добавьте шаги генерации Sigstore‑аттестаций в релизные workflow;
- документируйте для пользователей, как проверять аттестации.
5. Работа с зависимостями
-
Подключите Dependabot или Renovate:
- настройте группировку обновлений и cooldown‑периоды для сторонних зависимостей;
- для своих first‑party пакетов cooldown можно ослабить.
-
Регулярно пересматривайте список зависимостей:
- удаляйте редко используемые и тяжёлые;
- по возможности избегайте пакетов с бинарными блобами.
-
Если вы активно завязаны на конкретные библиотеки:
- вступите в их чат/форум/список рассылки;
- по возможности контрибьютите в их CI/CD и безопасность.
Astral честно говорит: этот набор практик — не окончательный список, а снимок состояния. Атакующие постоянно меняют подходы, и защиту приходится регулярно перестраивать. Но уже сейчас из этого опыта можно собрать рабочий каркас безопасности для любого серьёзного open source‑проекта — от линтера до фреймворка.