flawopen.com/Каталог/226
Marimo GHSL-2026-226: TOCTOU в workflow тестового релиза
Гонка временных меток в пределах одной секунды позволяла изменению pull request пройти одобрение тестового релиза и попасть в задания публикации TestPyPI и npm. Уязвимый workflow удалили; CVE не назначали.
Руководитель лаборатории одобряет конкретный образец, но лаборатория сверяет только секунду на часах. Если подменить образец в ту же секунду, замена выглядит одобренной. Workflow Marimo допустил такую ошибку с commit pull request, а затем передал собранный пакет в задания публикации.
Ключевые понятия и термины
TOCTOU- Time-of-check to time-of-use: ресурс меняется после проверки безопасности, но до его использования.
Публикация через OIDC- CI-задание обменивает удостоверение GitHub Actions на временные учётные данные реестра пакетов вместо хранения постоянного пароля.
Артефакт workflow- Набор файлов, передаваемый между заданиями GitHub Actions. Следующее задание должно считать артефакты недоверенных workflow недоверенными данными.
GHSL-2026-226- Идентификатор advisory GitHub Security Lab для этой ошибки workflow Marimo. CVE в advisory не назначен.
CWE-367 / CWE-829- В advisory указаны гонка между проверкой и использованием, а также выполнение функциональности из недоверенной области управления.
Связи со стандартами
Пошаговый сценарий атаки
Сопровождающий разрешает тестовый релиз
Сопровождающий оставляет комментарий в pull request, запуская workflow тестового релиза Marimo. Разрешение должно относиться к проверенному состоянию pull request.
Head pull request меняется в ту же секунду
Workflow сравнивает pushed_at репозитория с created_at комментария после преобразования в целые секунды. Push в ту же секунду даёт равные значения.
Уязвимая проверка принимает равенство
Удалённый workflow отклонял только pushed_at, строго большее времени комментария. Равенство проходило, и обновлённый commit сохранялся.
Недоверенный код собирает артефакты пакетов
Задание получало этот commit и запускало actions и скрипты сборки из репозитория. Результаты загружались как артефакты и передавались заданиям публикации без повторной сборки из доверенного commit.
Полномочия публикации достигают недоверенного результата
Задания TestPyPI и npm использовали права публикации OIDC. Advisory описывает возможность передачи артефакта в публикацию; о реальной компрометации пакета не сообщается.
Исходный код: Уязвимый vs Защищённый вариант
GHSL-2026-226 сообщает, что уязвимый workflow удалён в PR #10765; это не утверждение, что проект применил показанную замену сравнения. В старой проверке использовалось -gt, поэтому равные секундные значения проходили. Иллюстративная проверка -ge отклоняет равенство, но лучше связывать разрешение с точным проверенным commit. Отделяйте недоверенные сборки от OIDC-заданий, пересобирайте из разрешённого SHA и проверяйте происхождение перед публикацией. Эксплойт-payload не приводится.
# Удалённый workflow marimo-bot: сравнение целых секунд
if [[ $(date -d "$pushed_at" +%s) -gt $(date -d "$COMMENT_AT" +%s) ]]; then
exit 1
fi
# Полученный head_sha checkout-ился, а артефакты
# передавались отдельным заданиям публикации.
# Только иллюстративный контроль; GHSL сообщает, что уязвимый
# workflow удалили, а не исправили на месте.
if [[ $(date -d "$pushed_at" +%s) -ge $(date -d "$COMMENT_AT" +%s) ]]; then
exit 1
fi
# Более надёжная схема: разрешить проверенный неизменяемый SHA,
# пересобрать его в доверенном задании и опубликовать проверенный результат.
Чек-лист по защите системы для инженеров
- ✓Удалите или замените затронутые копии удалённого workflow marimo-bot и проверьте, что текущий репозиторий не включает уязвимый путь публикации.
- ✓Связывайте одобрение сопровождающего с точным неизменяемым SHA pull request и завершайте работу ошибкой, если head меняется до checkout.
- ✓Не используйте секундные временные метки как единственное доказательство того, что изменяемая ветка соответствует одобренной версии.
- ✓Собирайте недоверенные pull request без учётных данных публикации; оставляйте id-token: write только отдельному доверенному заданию публикации.
- ✓Повторно собирайте пакеты из разрешённого commit в доверенном процессе публикации, а не продвигайте артефакты недоверенного кода.
- ✓Проверяйте происхождение артефакта, ревизию исходников, содержимое пакета и назначение до публикации в TestPyPI или npm.
- ✓Считайте advisory GHSL доказательством уязвимого пути, но не фактом компрометации или эксплуатации пакета.
Источники
- Advisory GitHub Security Lab GHSL-2026-226 — reported by Jaroslav Lobačevski
- PR Marimo #10765 с удалением уязвимого workflow
- GitHub Security Lab: предотвращение pwn requests
- MITRE CWE-367: гонка проверки и использования
- MITRE CWE-829: включение функциональности из недоверенной области управления
- Связанный, но отдельный случай workflow: JupyterLab CVE-2026-84973