OpenSSF Scorecard / ビルドの守り方

Token-Permissions
CI のトークン権限が絞られているか

GitHub Actions のワークフローが、必要以上に強い権限のトークンを持っていないかを見るチェックです。既定のままだと書き込み権限が付くため、明示的に絞っていないと低い点になります。

何を見るチェックか

GitHub Actions のワークフローには、GITHUB_TOKEN という自動発行のトークンが渡されます。 Scorecard は、そのトークンにどこまでの権限が与えられているかを、 ワークフローファイルの permissions: の記述から調べます。

見ているのは主に次の点です。

  • ワークフロー全体(トップレベル)に permissions: read-all などの読み取りのみ指定があるか
  • 書き込みが要るジョブにだけ、必要な範囲で permissions が指定されているか
  • contents: writepackages: write のような強い権限が、ジョブ単位に限定されているか

トップレベルで読み取りのみに絞り、必要なジョブだけ個別に緩める、 という書き方が最も高く評価されます。

点が低いと何を意味するか

点が低いということは、CI が持っている権限が、その処理に必要な範囲より広い可能性がある、 という意味です。

CI で任意のコードが実行されてしまう状況(依存の乗っ取り、悪意ある Pull Request など)が 起きたとき、権限の広さがそのまま被害の大きさになります。

  • contents: write があれば、リポジトリのコードを書き換えられる
  • packages: write があれば、パッケージを公開できる
  • id-token: write があれば、外部サービスへの認証を取得できる

逆に読み取りだけに絞ってあれば、同じことが起きてもできることが限られます。

これは「攻撃を受けている」ではなく、事故が起きたときの被害範囲の話です。

誤解しやすい点

permissions: を書いていないだけで低く出ます。ここが最も多いケースです。

GitHub Actions は、permissions: を明示していない場合、 リポジトリまたは組織の既定値を使います。既定が「読み書き」のままだと、 すべてのワークフローが書き込み権限を持ちます。

つまりこの項目が低いプロジェクトの大半は、 意図して広い権限を与えているのではなく、既定のまま何も書いていないだけです。

また、次の場合も低く出ます。

  • リポジトリ設定側で既定を読み取りのみにしている場合。 実際には絞られていますが、Scorecard はワークフローファイルしか見ないため、 その設定を読み取れません。
  • GitHub Actions を使っていない場合。 検査対象が無いので評価されません。
  • リリースや自動コミットのために、本当に書き込みが要る場合。 必要な権限を与えているだけでも、トップレベルに書かれていれば減点されます。

「絞っていない」であって「漏れている」ではありません。

採用する側が確認すべきこと

利用者の立場では、この項目はそのプロジェクトの CI が乗っ取られたときの被害の大きさを示します。 直接あなたのコードに影響するものではありません。

見るとすれば、次の組み合わせです。

  1. リリース成果物が CI で自動生成されているか。 自動生成なら、CI の権限がそのままリリースの汚染につながります。

  2. Pinned-DependenciesDangerous-Workflow を合わせて見る。 「固定していない依存」×「広い権限」×「危険な書き方」が重なると、 CI が入口になる経路が現実的になります。単独で見ても意味は薄いです。

  3. 自分のプロジェクト側の権限を絞る。 相手側は変えられませんが、自分の CI は今日から絞れます。

メンテナーなら何を改善できるか

2か所を直すだけで、多くの場合は満点になります。

1. ワークフローのトップレベルで読み取りのみにする

name: CI

permissions:
  contents: read

on: [push, pull_request]

2. 書き込みが要るジョブにだけ、必要な権限を足す

jobs:
  release:
    permissions:
      contents: write      # リリースを作るため
      id-token: write      # provenance を付けるため

あわせて、リポジトリ設定の Settings → Actions → General → Workflow permissionsRead repository contents and packages permissions にしておくと、 新しく足したワークフローも既定で絞られます。

組織であれば、組織設定で同じことを一括で指定できます。

あわせて読む