9件すべて Scorecard が機械的に検出したセキュリティ・ベストプラクティス違反であり、 実害のある脆弱性ではない。ただし #182 (paper-review.yml の top-level write 権限) は GITHUB_TOKEN を最小権限化する観点で真の修正が必要。 他の High 3件は既に job-level スコープを切っており、Scorecard の検出ロジックの粒度の問題で 残っている false-positive 寄りのもの。Medium 3件 (Pinned-Dependencies) は OSS-Fuzz 慣行と 噛み合わない部分があり、コスト対効果の判断が必要。
contents: read にdocs/scorecard-governance-setup.html の続編)| # | カテゴリ | Sev | ファイル | 判定 |
|---|---|---|---|---|
| #182 | Token-Permissions | High | .github/workflows/paper-review.yml:32 | 修正必須 |
| #181 | Token-Permissions | High | .github/workflows/zenn-deploy-trigger.yml:14 | 運用判断 (受容可) |
| #180 | Token-Permissions | High | .github/workflows/sync-zenn-qiita.yml:16 | 運用判断 (受容可) |
| #179 | Token-Permissions | High | .github/workflows/release.yml:134 | 運用判断 (受容可) |
| #8 | Branch-Protection | High | (repo settings) | 設定追加推奨 |
| #175 | Pinned-Dependencies | Medium | .clusterfuzzlite/build.sh:8 | 低優先 (OSS-Fuzz 環境) |
| #174 | Pinned-Dependencies | Medium | Dockerfile:6 | 判断 (hash pin コスト) |
| #173 | Pinned-Dependencies | Medium | .clusterfuzzlite/Dockerfile:1 | 修正推奨 (low cost) |
| #57 | CII-Best-Practices | Low | (badge 未登録) | 後回し可 |
.github/workflows/paper-review.yml:31-34contents: write / issues: write / pull-requests: write を付与している。Scorecard は top-level write 権限を「ワークフロー内のあらゆる action にトークンが流れる」として High 判定。# 31-34行目を以下に置換
permissions:
contents: read
concurrency:
group: paper-review
cancel-in-progress: false
jobs:
review:
name: Review 10 papers and file pending candidates
runs-on: ubuntu-latest
permissions:
contents: write # commit state.json + pending stubs to bot branch
issues: write # file daily summary issue
pull-requests: write # open bot PR
steps:
...
permissions: を書いた瞬間、その job 内では top-level が無効化され job-level だけが効く。差し替えで実行影響なし。review 1個だけなので機械的に移動するだけで完了。.github/workflows/zenn-deploy-trigger.yml:13-14contents: read。job-level で contents: write を最小限付与済 (push の為に必須)。write 出現を High カウントするため、job-level でも残る。これはツール側の設計で、現状の構成は GitHub Actions のベストプラクティスに完全準拠している。3案あり、どれを選ぶかは運用ポリシー次第。
docs/scorecard-governance-setup.html に「job-level write は許容、top-level write は禁止」の方針を追記し、本アラートを Scorecard 側で dismiss する。GITHUB_TOKEN をやめ、専用 SSH デプロイキーで push する。contents: 権限自体を不要にできるが、シークレット管理コストが増える。empty commit を打つだけのワークフローには過剰。actions/create-github-app-token で発行。最小権限を厳密化できるが、運用が重い。.github/workflows/sync-zenn-qiita.yml:15-16contents: read + job-level contents: write の正しい構成。public/ ディレクトリを bot push し、Qiita CLI で publish。#181 と同じく、受容+ドキュメント化が現実解。Qiita publish 部分は別途 QIITA_TOKEN シークレットを使うので、GITHUB_TOKEN 側を厳しく絞るインセンティブは低い。
.github/workflows/release.yml:133-134 (github-release job)contents: read + github-release job のみ contents: write (Release 作成のため必須)。build / publish-pypi は contents: read + OIDC id-token: write で正しくスコープ済。contents: write 1箇所を機械的に検出。contents: write という構成は GitHub 公式 release workflow の標準形。CHANGELOG.md / CLAUDE.md の release 規約とも一致しているため、変更すべきではない。softprops/action-gh-release を GITHUB_TOKEN ではなく App Token で動かせば contents: write を完全に剥がせるが、PR/tag フローの監査トレイル (release が誰名義で作られたか) が変わる。慎重に。tests, codeql, scorecard--no-gpg-sign 禁止と整合)※ 既存の docs/scorecard-governance-setup.html に該当章があるかは要確認。なければ追記。
.clusterfuzzlite/build.sh:8 (pip3 install --no-cache-dir .).) の install で --require-hashes 等のハッシュ検証なし。pip install の出現自体を機械的に検出。このまま受容で良い。ClusterFuzzLite の build はホスト fuzz 環境内で完結し、wheel/sdist を index から取らないため攻撃面が無い。Scorecard 側で dismiss reason = "No PyPI download — installs local source only" として閉じる。
Dockerfile:6 (pip install ... 'pip==26.1.1' 'build==1.5.0')--require-hashes + --no-deps による SHA-256 hash pinning。COPY requirements-build.txt /tmp/
RUN pip install --no-cache-dir --require-hashes -r /tmp/requirements-build.txt
requirements-build.txt:
pip==26.1.1 \
--hash=sha256:<...>
build==1.5.0 \
--hash=sha256:<...>
+ pip-compile --generate-hashes でハッシュ生成、依存 update のたびに pin を更新する CI が必要。
build stage の依存は pip と build の2つだけで、いずれも PyPI 公式パッケージ。hash pin の運用コストの方が高い可能性。Dependabot で version pin を継続管理する方が ROI が高い。
.clusterfuzzlite/Dockerfile:1FROM gcr.io/oss-fuzz-base/base-builder-python がタグなし・digest なし (=latest 相当)。# 最新 digest を取得して固定
FROM gcr.io/oss-fuzz-base/base-builder-python@sha256:<digest>
本体 Dockerfile は既に python:3.14-slim@sha256:7a500125... で pin 済なので、同じ流儀に合わせるだけ。digest 取得は次のいずれか:
docker pull gcr.io/oss-fuzz-base/base-builder-python && docker inspect --format='{{index .RepoDigests 0}}' gcr.io/oss-fuzz-base/base-builder-python運用: Dependabot は GCR の digest 更新も検知できるよう package-ecosystem: docker を .github/dependabot.yml に追加 (まだ無ければ)。
30〜60分の self-assessment フォーム記入で Passing badge は取得可能。README に bestpractices.dev のバッジを貼ると外部信頼度↑。docs/openssf-best-practices.md 既存ドキュメントの内容を踏まえると、すでにかなりの基準を満たしているはず。優先度低だがコストも低いので、空き時間にやれる。
.github/workflows/paper-review.yml の permissions を job-level に移動 (#182).clusterfuzzlite/Dockerfile の base image を digest pin (#173)[Unreleased] に "ci: tighten paper-review GITHUB_TOKEN scope; pin clusterfuzzlite base image" を追加docs/scorecard-governance-setup.html に方針を追記 (job-level write 受容、top-level write 禁止)Dockerfile の pip hash pin 化 (#174) — 採用するか否か決定.clusterfuzzlite/build.sh の扱い (#175) — dismiss か no-op か決定