Code Scanning アラート精査レポート

対象: killertcell428/aigis · 取得日 2026-05-19 · 検出元 Scorecard · 件数 9 (High 5 / Medium 3 / Low 1)

1. エグゼクティブサマリ

5
High
3
Medium
1
Low
3
即時修正推奨
3
改善余地あり
3
運用判断 / 受容

9件すべて Scorecard が機械的に検出したセキュリティ・ベストプラクティス違反であり、 実害のある脆弱性ではない。ただし #182 (paper-review.yml の top-level write 権限) は GITHUB_TOKEN を最小権限化する観点で真の修正が必要。 他の High 3件は既に job-level スコープを切っており、Scorecard の検出ロジックの粒度の問題で 残っている false-positive 寄りのもの。Medium 3件 (Pinned-Dependencies) は OSS-Fuzz 慣行と 噛み合わない部分があり、コスト対効果の判断が必要。

推奨対応順

  1. 即対応 — #182 paper-review.yml の権限を job-level に移し top-level を contents: read
  2. 即対応 — #173 .clusterfuzzlite/Dockerfile の base image を digest pin
  3. 近日対応 — #8 master の Branch Protection ルール設定 (docs/scorecard-governance-setup.html の続編)
  4. 判断 → ドキュメント化 — #179/#180/#181 (job-level write は許容方針として記録)
  5. 判断 → ドキュメント化 — #174/#175 (pip hash pinning は CI 維持コスト次第)
  6. 後回し可 — #57 CII Best Practices badge の取得

2. アラート一覧

#カテゴリSevファイル判定
#182Token-PermissionsHigh.github/workflows/paper-review.yml:32修正必須
#181Token-PermissionsHigh.github/workflows/zenn-deploy-trigger.yml:14運用判断 (受容可)
#180Token-PermissionsHigh.github/workflows/sync-zenn-qiita.yml:16運用判断 (受容可)
#179Token-PermissionsHigh.github/workflows/release.yml:134運用判断 (受容可)
#8Branch-ProtectionHigh(repo settings)設定追加推奨
#175Pinned-DependenciesMedium.clusterfuzzlite/build.sh:8低優先 (OSS-Fuzz 環境)
#174Pinned-DependenciesMediumDockerfile:6判断 (hash pin コスト)
#173Pinned-DependenciesMedium.clusterfuzzlite/Dockerfile:1修正推奨 (low cost)
#57CII-Best-PracticesLow(badge 未登録)後回し可

3. アラート別の詳細と修正提案

#182 Token-Permissions 修正必須

ファイル
.github/workflows/paper-review.yml:31-34
原因
top-level で contents: write / issues: write / pull-requests: write を付与している。Scorecard は top-level write 権限を「ワークフロー内のあらゆる action にトークンが流れる」として High 判定。
リスク
Anthropic API キー込みのワークフローで、悪意のある依存 (uv / setup-python のサプライチェーン経由) があった場合、トークン奪取によりリポジトリ書き込みまで連鎖し得る。
修正案 — top-level を read に、job-level で必要権限を付与
# 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:
      ...
確認ポイント

#181 Token-Permissions 運用判断 — 受容可

ファイル
.github/workflows/zenn-deploy-trigger.yml:13-14
現状
top-level は既に contents: read。job-level で contents: write を最小限付与済 (push の為に必須)。
Scorecard 判定理由
Scorecard は あらゆる write 出現を High カウントするため、job-level でも残る。これはツール側の設計で、現状の構成は GitHub Actions のベストプラクティスに完全準拠している。
対応案

3案あり、どれを選ぶかは運用ポリシー次第。

  1. 受容してドキュメント化 (推奨): docs/scorecard-governance-setup.html に「job-level write は許容、top-level write は禁止」の方針を追記し、本アラートを Scorecard 側で dismiss する。
  2. Deploy Key 化: GITHUB_TOKEN をやめ、専用 SSH デプロイキーで push する。contents: 権限自体を不要にできるが、シークレット管理コストが増える。empty commit を打つだけのワークフローには過剰。
  3. 外部 App Token 化: GitHub App を作って actions/create-github-app-token で発行。最小権限を厳密化できるが、運用が重い。

#180 Token-Permissions 運用判断 — 受容可

ファイル
.github/workflows/sync-zenn-qiita.yml:15-16
現状
#181 と同様、top-level contents: read + job-level contents: write の正しい構成。
用途
Zenn → Qiita 変換後の public/ ディレクトリを bot push し、Qiita CLI で publish。
対応案

#181 と同じく、受容+ドキュメント化が現実解。Qiita publish 部分は別途 QIITA_TOKEN シークレットを使うので、GITHUB_TOKEN 側を厳しく絞るインセンティブは低い。

#179 Token-Permissions 運用判断 — 受容可 / 一部最適化余地

ファイル
.github/workflows/release.yml:133-134 (github-release job)
現状
top-level contents: read + github-release job のみ contents: write (Release 作成のため必須)。build / publish-pypicontents: read + OIDC id-token: write で正しくスコープ済。
Scorecard 判定理由
job-level の contents: write 1箇所を機械的に検出。
対応案

#8 Branch-Protection 設定追加推奨

対象
repository settings (no file)
原因
master ブランチに Branch Protection ルールが未設定 (または Scorecard が読み取れる範囲では未設定)。
リスク
direct push / force push / CI 未通過マージが理論上可能。CLAUDE.md の release プロセス (PR マージ → tag) を制度的に強制できない。
推奨ルール (Settings → Branches → Add rule)

※ 既存の docs/scorecard-governance-setup.html に該当章があるかは要確認。なければ追記。

#175 Pinned-Dependencies 低優先

ファイル
.clusterfuzzlite/build.sh:8 (pip3 install --no-cache-dir .)
原因
aigis 自身 (ローカルパス .) の install で --require-hashes 等のハッシュ検証なし。
リスク評価
ローカルソースを install しているため通常意味でのサプライチェーンリスクは低い。Scorecard はチェックロジック上 pip install の出現自体を機械的に検出。
対応案

このまま受容で良い。ClusterFuzzLite の build はホスト fuzz 環境内で完結し、wheel/sdist を index から取らないため攻撃面が無い。Scorecard 側で dismiss reason = "No PyPI download — installs local source only" として閉じる。

#174 Pinned-Dependencies 判断 — hash pin か受容か

ファイル
Dockerfile:6 (pip install ... 'pip==26.1.1' 'build==1.5.0')
現状
バージョンは pin 済だが、Scorecard が要求するのは --require-hashes + --no-deps による SHA-256 hash pinning。
案A — 完全 hash pin (Scorecard を Pass にする)
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 が必要。

案B — 受容 (推奨)

build stage の依存は pipbuild の2つだけで、いずれも PyPI 公式パッケージ。hash pin の運用コストの方が高い可能性。Dependabot で version pin を継続管理する方が ROI が高い。

#173 Pinned-Dependencies 修正推奨

ファイル
.clusterfuzzlite/Dockerfile:1
原因
FROM gcr.io/oss-fuzz-base/base-builder-python がタグなし・digest なし (=latest 相当)。
リスク
base image が更新されると fuzz harness の build 結果が変わる (再現性無し)。供給元 (Google OSS-Fuzz) は信頼できるが「再現可能ビルド」観点で問題。
修正案
# 最新 digest を取得して固定
FROM gcr.io/oss-fuzz-base/base-builder-python@sha256:<digest>

本体 Dockerfile は既に python:3.14-slim@sha256:7a500125... で pin 済なので、同じ流儀に合わせるだけ。digest 取得は次のいずれか:

運用: Dependabot は GCR の digest 更新も検知できるよう package-ecosystem: docker.github/dependabot.yml に追加 (まだ無ければ)。

#57 CII-Best-Practices 後回し可

対象
OpenSSF Best Practices Badge (旧 CII Best Practices)
原因
bestpractices.dev での self-certification 未取得。
対応案

30〜60分の self-assessment フォーム記入で Passing badge は取得可能。README に bestpractices.dev のバッジを貼ると外部信頼度↑。docs/openssf-best-practices.md 既存ドキュメントの内容を踏まえると、すでにかなりの基準を満たしているはず。優先度低だがコストも低いので、空き時間にやれる。

4. 実装プラン (採用された場合のチェックリスト)

Phase 1 — 1 PR で完結する低リスク変更
Phase 2 — リポジトリ設定 (UI 操作)
Phase 3 — 判断が必要な改善

5. 参考