OpenSSF Scorecard / ビルドの守り方

Packaging
公式のパッケージとして配布されているか

npm や PyPI などのレジストリへの公開が、CI から自動で行われているかを見るチェックです。手作業で公開している場合や、公開のワークフローが読み取れない場合は低く出ます。

何を見るチェックか

Scorecard は、CI の設定の中にパッケージを公開する処理があるかを探します。

見ているのは、たとえば次のようなものです。

  • GitHub Actions で npm publish を実行している
  • pypa/gh-action-pypi-publish を使っている
  • docker/build-push-action でイメージを公開している
  • Maven / NuGet / RubyGems の公開ステップがある
  • GitHub Packages への公開

見つかれば高い点になり、無ければ低くなります。

この項目の狙いは、公開の経路が自動化され、記録に残っているかです。 誰かの手元の端末から公開されるより、 CI から公開されるほうが、何から作られたかを後から追えます。

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

点が低いということは、公開の経路が確認できないという意味です。

考えられる状況は次のとおりです。

  • メンテナーが手元の端末から npm publish している
  • 公開の手順がリポジトリの外にある
  • そもそもレジストリに公開していない(GitHub から直接使う種類のもの)

手元からの公開が問題になりうるのは、

  • その端末が汚染されていた場合、汚染された成果物が公開されうる
  • 公開用の認証情報が個人の端末に置かれている
  • 何のコミットから作られたのかを、利用者が確認できない

からです。これも「事故が起きたときに追えるか」という話であって、 今何かが起きているという指摘ではありません。

誤解しやすい点

レジストリに公開されているのに 0点、というケースがよくあります。

Scorecard が見ているのは CI の設定ファイルです。 実際に npm や PyPI にパッケージが存在するかどうかは見ていません。

そのため、次はすべて低く出ます。

  • 手作業で公開しているが、きちんと運用されている
  • 公開は別のリポジトリや社内の仕組みから行っている
  • 公開ワークフローの書き方が Scorecard の想定と違う
  • Go のように、レジストリへの公開という工程が存在しないエコシステム (Go はリポジトリのタグがそのままバージョンになります)

とくに最後は構造的な問題で、 Go のライブラリは Packaging を満たしようがないことがあります。

逆に、CI から公開していれば中身が検証されている、という意味でもありません。 公開が自動化されているかを見ているだけです。

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

利用者としては、Packaging の点数より、実際の配布物のほうを見るべきです。

  1. レジストリのページを開く。 npm / PyPI / Packagist のページで、公開者、公開日、バージョンの並びを確認します。

  2. npm なら provenance の表示を見る。 GitHub Actions から公開されている場合、 「どのリポジトリのどのワークフローから作られたか」が表示されます。 これは Packaging の点数より、はるかに直接的な材料です。

  3. リポジトリとパッケージの紐付けを確認する。 パッケージの repository 欄は自己申告で、正しいとは限りません。 名前が似た別のパッケージを掴まないよう、公開者と説明を確認してください。

  4. Signed-Releases と合わせて読む。 公開が自動化され、かつ来歴が付いていれば、経路をひととおり追えます。

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

公開を GitHub Actions に移すと、この項目とあわせて Signed-Releases にも効きます。

npm の例

on:
  release:
    types: [published]

permissions:
  contents: read
  id-token: write        # provenance に必要

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          registry-url: 'https://registry.npmjs.org'
      - run: npm ci
      - run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

PyPI の例

pypa/gh-action-pypi-publish と Trusted Publishing を使うと、 API トークンを保存せずに公開できます。 シークレットを持たないぶん、漏洩の余地がなくなります。

共通のこつ

  • 公開は release イベントか、タグの push を起点にする
  • 公開ジョブにだけ id-token: write を付ける → Token-Permissions
  • 個人の端末に公開用トークンを置かない
  • Go のように公開工程が無いエコシステムでは、この項目は満たせません。無理に追わなくてかまいません

あわせて読む