FlawOpen

flawopen.com/GitHub Actionsのセキュリティ/workflowスクリプトインジェクション

GitHub Actionsのスクリプトインジェクションはどう起き、どう防ぐ?

高権限時の影響は重大 CWE-78 CI/CD workflowのセキュリティ
かんたんに説明

Bash起動前にissueタイトルやpull requestの値をscriptへ埋め込むと、workflowがデータをshell構文に変えることがあります。名前を指示と誤解する名札プリンターのようなものです。環境変数で値を渡し、データとして使う際は展開を引用符で囲めば、Bashは値をscriptと分けて受け取ります。影響はtoken、secret、runner、イベントにも左右されます。

信頼できないコンテキストタイトル、本文、branch名、label、commit messageなどのGitHubイベント値。外部ユーザーが制御できる文字列として扱います。
式の展開GitHubはshell起動前に ${{ ... }} を評価します。run:では入力がscriptソースへ挿入されることがあります。
環境変数での受け渡しenv:への割り当てはプロセスデータとして値を渡します。shell展開を引用し、evalや動的script生成を避けます。
権限境界イベントとworkflowがtoken権限、利用可能なsecret、runnerアクセスを決めます。影響はjobが到達できる資源に限られます。

原因:shell解析前にデータが埋め込まれる

GitHubはrunステップのshell起動前に式を展開します。信頼できないタイトルを直接埋め込むと、shellプログラムが変わる可能性があります。env:経由の値はscript本文から分離され、引用符で囲めば通常コマンドへの引数として保たれます。ただし、後でevalや別のインタープリター、引数をコードとして扱うツールへ渡す場合は安全ではありません。GitHubはイベント値を攻撃者が制御し得る入力として扱います。

.github/workflows/triage.yml(危険な埋め込み)危険
# 危険:イベントデータが生成shell scriptの一部になる
name: Issue Triage
on:
  issues:
    types: [opened]

permissions:
  contents: read

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - name: Print issue title
        run: |
          printf 'Title: %s\n' "${{ github.event.issue.title }}"
.github/workflows/triage.yml(データを分離)対策済み
# より安全:イベント値を環境変数で渡す
name: Issue Triage
on:
  issues:
    types: [opened]

permissions:
  contents: read

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - name: Print issue title
        env:
          ISSUE_TITLE: ${{ github.event.issue.title }}
        run: |
          printf 'Title: %s\n' "$ISSUE_TITLE"

攻撃経路の概要

Step 1

利用者がイベント値を制御

公開issueやpull requestのタイトル、branch名がworkflow入力になります。

Step 2

workflowがshellソースへ埋め込む

run:内の直接的な ${{ github.event... }} はBash解析前に展開されます。

Step 3

shellが変更されたプログラムを解釈

値がshell構文を変えるとjobのプロセス権限でコマンドが動きます。引用符付き引数のままなら注入は起きません。

Step 4

jobの権限が影響を決める

侵害されたjobが触れられるのは実行に開かれた資源だけです。GITHUB_TOKEN権限、secret、runnerを確認し、issueイベントとpull_request_targetを精査します。

強化チェックリスト

一次資料

関連するセキュリティトピックと分析を見る:セキュリティ総合ディレクトリ →
関連項目 Cosign GHSA-fx35-mq7g-6g98:Bundle 検証回避 Dependency Confusion:リスクと対策 Docker ソケット公開のリスクと対策