FlawOpen

flawopen.com/ディレクトリ/226

● CWE-367 / CWE-829 · 高
セキュリティ研究 · FlawOpen

Marimo GHSL-2026-226:テストリリースワークフローの TOCTOU

同じ秒に発生するタイムスタンプ競合により、Pull Request の更新がメンテナーのテストリリース承認をすり抜け、TestPyPI と npm の公開ジョブへ到達する可能性がありました。脆弱なワークフローは削除され、CVE は割り当てられていません。

💡 わかりやすい解説 (ELI5)

研究室の責任者が特定のサンプルを承認しますが、研究室は時計の秒だけを確認します。同じ秒にサンプルを差し替えると、交換品も承認済みに見えてしまいます。Marimo のワークフローは Pull Request のコミットで同じ誤りを起こし、ビルドしたパッケージを公開ジョブに渡しました。

主要な概念と専門用語

TOCTOU
Time-of-check to time-of-use:セキュリティ確認後、リソースが使われる前にそのリソースが変化する問題です。
OIDC 公開
CI ジョブが GitHub Actions の ID をパッケージレジストリの短期資格情報と交換し、長期パスワードを保存せずに公開します。
ワークフローアーティファクト
GitHub Actions のジョブ間で渡されるファイル群です。後続ジョブは、信頼できないワークフローのアーティファクトを未信頼入力として扱う必要があります。
GHSL-2026-226
この Marimo ワークフローの欠陥に対する GitHub Security Lab のアドバイザリ ID です。CVE は割り当てられていません。
CWE-367 / CWE-829
アドバイザリは検査と使用の間の競合、および信頼されない制御領域の機能実行を指摘しています。

フレームワーク対応

ステップ・バイ・ステップの攻撃フロー

ステップ 1

メンテナーがテストリリースを承認

メンテナーが Pull Request にコメントし、Marimo のテストリリースワークフローを起動します。承認はレビューした Pull Request の状態に対して行われる想定です。

ステップ 2

同じ秒の間に Pull Request の head が変わる

ワークフローは pushed_at とコメントの created_at を整数秒に変換して比較します。同じ秒の push は同じ値になります。

ステップ 3

脆弱なチェックが同じ値を受け入れる

削除されたワークフローは、コメント時刻より厳密に後の pushed_at だけを拒否していました。同じ値は通過し、更新後のコミットが記録されました。

ステップ 4

未信頼コードがパッケージ成果物を作る

ジョブはそのコミットを checkout し、リポジトリ管理下の action とビルドスクリプトを実行しました。成果物はアップロードされ、信頼できるコミットから再ビルドされずに後続の公開ジョブで使われました。

ステップ 5

公開権限が未信頼の出力に及ぶ

TestPyPI と npm のジョブは OIDC 公開権限を使っていました。アドバイザリは成果物が公開に到達し得たと説明していますが、実際のパッケージ侵害は報告していません。

ソースコード比較:脆弱 vs 堅牢化

GHSL-2026-226 は脆弱な workflow が PR #10765 で削除されたと報告しています。ここで示す比較演算子の変更をプロジェクトが適用したという意味ではありません。旧チェックは -gt を使い、秒単位で等しい時刻を通していました。説明用の -ge は等しい値を拒否しますが、承認をレビュー済みの正確なコミットに結び付ける方が強固です。未信頼ビルドと OIDC ジョブを分離し、承認された SHA から再ビルドして公開前に来歴を検証してください。exploit payload は含みません。

脆弱な実装
# 削除済み marimo-bot workflow:秒単位の比較
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 を承認し、
# 信頼されたジョブで再ビルドして検証済み出力を公開します。

エンジニアリング&システム堅牢化チェックリスト

参考資料