diff --git a/.clusterfuzzlite/Dockerfile b/.clusterfuzzlite/Dockerfile index b9844a4..862498e 100644 --- a/.clusterfuzzlite/Dockerfile +++ b/.clusterfuzzlite/Dockerfile @@ -1,4 +1,4 @@ -FROM gcr.io/oss-fuzz-base/base-builder-python +FROM gcr.io/oss-fuzz-base/base-builder-python@sha256:e24e8e50612617101dd10038502f68268ab45f31d79a3722c230464277a951b3 # Install minimal build deps RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/.github/workflows/paper-review.yml b/.github/workflows/paper-review.yml index 2103394..0b01624 100644 --- a/.github/workflows/paper-review.yml +++ b/.github/workflows/paper-review.yml @@ -29,9 +29,7 @@ on: default: "10" permissions: - contents: write # to commit state.json + pending stubs - issues: write # to file the daily summary issue - pull-requests: write # so the bot can open a PR with the new pending files + contents: read concurrency: group: paper-review @@ -41,6 +39,10 @@ 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 with new pending files steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 diff --git a/docs/scorecard-alerts-2026-05-19.html b/docs/scorecard-alerts-2026-05-19.html new file mode 100644 index 0000000..acdf477 --- /dev/null +++ b/docs/scorecard-alerts-2026-05-19.html @@ -0,0 +1,351 @@ + + +
+ +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 か決定本リポは既に以下の Branch Protection を有効化済(gh api repos/killertcell428/aigis/branches/master/protection で確認):
Lint & Type Check, Test / Python 3.11, Test / Python 3.12required_approving_review_count = 0 — 1 人開発のため意図的Scorecard alert #8 Branch-Protection (High) が残っているのは、最後の required_approving_review_count = 0 に起因する。これは「自分の PR を自分でマージできる必要がある」というソロ開発の現実的制約で、外部コントリビュータが現れたら approval=1 に上げる方針。Won't fix として dismiss する。
dismiss 文言テンプレ:
+Won't fix — solo developer repo. Branch protection enforces status
+checks, signed commits, linear history, and admin enforcement; only
+required_approving_review_count is 0 (would block all merges otherwise).
+Will raise to 1 once a second maintainer joins.
+See docs/scorecard-governance-setup.html §1.
+
Scorecard 指摘: Repository was created within the last 90 days
後回しでOK。先に他の項目を片付けてから検討。
++Scorecard が High / Medium で機械的に検出するが、構成上「これ以上絞れない/絞ると別のリスクが増える」種類のアラートを明示的に受容する方針を以下に定める。新しいアラートが同じカテゴリで上がった場合、本セクションに照らして dismiss 可否を判断する。 +
+ +contents: write は許容、top-level は禁止方針:
+permissions: contents: read(または最小権限)を設定する。write 権限は 必要な job の permissions: ブロックでのみ付与する。write を High として検出しても dismiss 可。根拠:
+GITHUB_TOKEN は job 単位でスコープされるため、job-level に絞った時点で他 job への漏出は防げる。write の出現を機械的にカウントするため、正しいスコープであっても High として残る既知の挙動。対応済アラート:
+ +| Alert | ファイル | 用途 | 判断 |
|---|---|---|---|
| #179 | +.github/workflows/release.yml:134 |
+ github-release job — GitHub Release 作成のため contents: write 必須 |
+ 受容 (build/publish-pypi job は OIDC 化済で contents: read) |
+
| #180 | +.github/workflows/sync-zenn-qiita.yml:16 |
+ Zenn→Qiita 変換後の public/ commit + push |
+ 受容 | +
| #181 | +.github/workflows/zenn-deploy-trigger.yml:14 |
+ Zenn deploy トリガーの empty commit push | +受容 | +
dismiss 文言テンプレ(Code scanning UI で使用):
+Won't fix — job-level permissions are correctly scoped per
+docs/scorecard-governance-setup.html §6.1.
+Top-level is contents:read; this job's write scope is the
+minimum required for its function.
+
+pip install は許容方針:
+--require-hashes)を導入する。pip install .) は hash pin 不要として受容する。Dockerfile / .clusterfuzzlite/Dockerfile ともに digest pin 済)。根拠:
+対応済アラート:
+ +| Alert | ファイル | 内容 | 判断 |
|---|---|---|---|
| #175 | +.clusterfuzzlite/build.sh:8 |
+ pip3 install --no-cache-dir . — ローカル aigis ソースの install |
+ 受容 (ネットワーク取得なし) | +
dismiss 文言テンプレ:
+Won't fix — installs local source only (no PyPI download),
+no supply-chain surface. See docs/scorecard-governance-setup.html §6.2.
+
+以下は受容も修正もせず、運用コストとのトレードオフを継続検討する:
+Dockerfile:6 の pip install pip==26.1.1 build==1.5.0 の hash pin 化。pip-compile --generate-hashes 運用が現実的か要検討。すべて設定後、Scorecard を再実行して結果を確認できます: