開発mdx-playgroundアクティブ

きっかけ

2026年5月1日に公表されたマネーフォワードのGitHub不正アクセス事件を読んだ。ソースコード一式・カード保持者370件分の氏名と下4桁・各種認証キーが流出した、というインシデントである。

記事の主旨はシンプルで、「認証情報の漏えい自体は防ぎきれない。だが、漏れたあとに被害がどこまで広がるかは、平時の設計でほぼ決まる」というもの。

自分のリポジトリは個人プロジェクトなので規模も影響範囲も違う。とはいえ、ブログ・財務データ閲覧・Cloudflareへの自動デプロイ・Claude Codeとの連携など、認証情報を扱う場面は意外に多い。「いま流出したら何が起きるか」を一度棚卸ししておきたい、と思った。

この記事は、対策を網羅的に並べた上で、自分のリポジトリで「やっていない・足りない」ものをチェックリスト化したものだ。同じ規模の個人開発者の参考になれば。

起きたことの要約

項目内容
公表日2026年5月1日
流出物ソースコード一式、カード保持者370件分の氏名(ローマ字)とカード番号下4桁、各種認証キー・パスワード
流出していないものカード番号全桁、有効期限、CVV、本番DB情報
対応認証情報無効化・鍵の一括ローテーション・銀行連携機能の一時停止

GitHub認証情報の漏えい経路として一般的に多いのは、開発者PCのマルウェア感染、公開リポジトリへの誤コミット、サードパーティ連携の侵害、フィッシングの4つ。今回の経路は公表されていないが、事後対応から見ても「鍵がコミットに含まれていた/環境変数管理が甘かった」状況は推測できる。

元記事が推奨している対策セット

元記事では以下のセットを推している。これは業界標準の構成で、自分の環境にも基本そのまま当てはまる。

  • 秘密検出: gitleaksをpre-commitとCIに、TruffleHogで過去履歴を定期スイープ、GitHub標準のSecret Scanning + Push Protection有効化
  • 履歴クリーンアップ: 検出された鍵は即時失効が最優先、git-filter-repoで履歴削除、全メンバー再クローン
  • 本番データ取扱: Faker/Mimesis等で合成データ生成、不可逆な仮名化・マスキングを必須化、本番データのリポジトリ持ち込み禁止
  • 秘密管理サービス: AWS Secrets Manager / SSM / GCP Secret Manager / Vault等への移行、環境別の鍵分離、有効期限と自動ローテーション、アクセス監査
  • 認証方式刷新: PAT廃止、GitHub Appの短期トークン、CI/CDはOIDC、残るPATはFine-grainedで権限最小化

元記事に書かれていないけど追加で入れたい対策

ひとり開発・小規模開発の文脈で、元記事の射程に入っていないが効果が高いと感じたものを足す。

GitHubの設定でいま無料で押せるボタン

  • Secret Scanning: 公開リポジトリは標準で有効。private/internalもPush Protection含めて有効化(Settings → Code security)
  • Push Protection (リポジトリ + ユーザーアカウント両方): Settings → Code security → Push protection。これが一番効く。コミット段階で押し戻される
  • Dependabot Alerts + Security Updates + Version Updates: 既知脆弱性のあるパッケージを自動でPR化
  • CodeQL Default Setup: 個人リポジトリは無料。Settings → Code security → Code scanning → Set up
  • Branch Protection / Ruleset: masterへの直push禁止、必須レビュー(個人なら自己レビューでもよい)、Force Push禁止、署名コミット必須、線形履歴
  • Required commit signing (GPG/SSH/Sigstore): なりすましコミット防止
  • 2FA強制 + Passkey: 個人アカウント設定。Organization化しているなら全メンバー強制
  • GitHub Apps化 / OIDC化: Cloudflare、AWS、GCP等のCI連携はPATをやめてOIDC連合認証に。CloudflareもOIDC対応済
  • GitHub Actionsの3rdパーティアクションのSHAピン留め: uses: actions/checkout@v4 ではなく @<commit-sha>。タグは差し替え可能なので
  • Workflow permissions のデフォルトを read のみに: Settings → Actions → General → Workflow permissions
  • fork PRからのsecrets読み出し禁止: Actionsのデフォルト設定で
  • Audit Log Streaming (Org+Enterpriseのみ): SIEMに飛ばす

ローカル開発側で入れたい層

  • husky + lint-staged + gitleaks pre-commit: コミット前に確実に止める層。CIでの検出は遅すぎる
  • detect-secrets: 既知のシークレットパターンをベースライン化して継続監視
  • eslint-plugin-no-secrets: JS/TSコード中の長文字列リテラルを検出
  • commit-msg hookでConventional Commits + 検証: コミットメッセージへの誤貼り付け防止
  • direnv / dotenvx: .env をコミットに含めずにローカルで使い回す。dotenvxは暗号化での保管も可能
  • Wrangler secret put (Cloudflare): Wranglerのプロジェクトでは wrangler secret put を使い、.dev.vars はgitignore。本番環境変数はダッシュボード/CIに置く
  • コミット署名: git config --global commit.gpgsign true
  • ghoコマンドラインのスコープ最小化: gh auth login で取るスコープを必要分のみ

Claude Code固有でできること

ここは元記事のスコープ外だが、AIエージェント時代に入った今、agent経由の意図せぬ情報露出を防ぐ層は重要度が上がっている。

  • CLAUDE.mdに .env 読み取り禁止ルールを書く: 既に自分のglobal CLAUDE.mdには入っている。プロジェクトCLAUDE.mdにも明示
  • PreToolUse hookでBashコマンドを検査: cat .envenvprintenvgrep -r .env などをブロック。settings.json で hook を設定
  • PreToolUse hookでgit commit前にgitleaks実行: コミットコマンドを検知したら gitleaks protect --staged を強制
  • permissionsでReadを .env* 拒否: settings.json の permissions.denyRead(./apps/web/.env*) を入れる
  • Subagentに権限を渡しすぎない: サブエージェント定義の Tools 欄で機密ファイルを触る必要のないものは Read を外す
  • MCPサーバーのトークンスコープ確認: gh、freee、google-workspace等のMCPはそれぞれ強い権限を持つ。不要なトークンは無効化
  • Claude Codeセッションログのローテーション: トランスクリプトに鍵を貼ってしまった場合に備えて、定期的に削除(session-backup スキルが該当)
  • Plan ModeをデフォルトON: 危険操作前に必ず人間が見る運用

本番データの扱い

個人ブログレベルだと該当しないが、財務データを表示する画面(apps/web/app/pages/配下)など、本番由来のシードを使っている場所は要注意。

  • シードデータはFakerで生成して固定seedで再現: テスト時に本番由来の数値を流用しない
  • D1のローカル開発DBを本番から取らない: wrangler d1 export した本番ダンプはローカルで開かない、もしくは仮名化スクリプトを通す
  • PII(個人情報・本人確認情報)はそもそも持たない: 持たなければ流出もしない。最強の対策

物理層・端末層

  • OSフルディスク暗号化 (BitLocker / FileVault)
  • EDR/MDR (Defender for Business、CrowdStrike等)。マルウェア経由の漏えいが一番多い経路なので
  • gh auth status で生きているトークンを定期棚卸し
  • macOS Keychain / Windows Credential Manager から古いトークンを削除
  • 使っていないGitHub Personal Access Tokenを失効: github.com → Settings → Developer settings → Personal access tokens

自分のリポジトリの現状と差分

ここからは mdx-playground の棚卸し。「やっている」「やっていない」を正直に書く。

やっていること

  • .env .env.*.gitignore
  • .dev.vars (Wrangler) も .gitignore
  • グローバルCLAUDE.mdに .env 読み取り禁止ルール
  • プロジェクトCLAUDE.mdにも .env 読み取り禁止ルール
  • CI/CDで使う鍵は secrets.* 経由(Cloudflare API Token、OG_SECRET、Claude Code OAuth)
  • 自動デプロイは無効化済(手動トリガーのみ、SSGメモリ問題対策と副次的にrelease coordinationの安全側にも寄与)
  • 公開記事用ディレクトリと内部メモ用ディレクトリ(internal/)が .gitignore ではないが分離済(公開可否が明示)

抜けていること(優先度順)

P0:今日中に入れたい

  • GitHub Push Protectionの有効化確認: Settings → Code security → Secret scanning → Push protection
  • GitHub Secret Scanningの履歴チェック: 過去のpushに既知シークレットが残っていないか
  • gitleaksでローカル全履歴スキャン: gitleaks detect --source . --log-opts="--all" を一度通す
  • TruffleHogで全履歴スキャン: 検証付きの方が確実
  • 過去のCloudflare API Tokenの棚卸し: 使っていないトークンの失効
  • GitHub Personal Access Tokenの棚卸し: 使っていないPATの失効
  • 2FA / Passkey設定の確認

P1:1週間以内に入れたい

  • husky + lint-staged + gitleaks pre-commit hook: コミット段階での防御
  • gitleaksをCI(GitHub Actions)に追加: PR時にスキャン
  • Dependabot Alerts / Security Updates / Version Updates 有効化
  • CodeQL Default Setup: 個人リポは無料
  • Branch Protection / Ruleset: masterへの直push制限・force push禁止
  • Workflow permissions を read のみに
  • GitHub Actionsの3rdパーティアクションをSHAピン留め: actions/checkoutpnpm/action-setupactions/setup-nodeanthropics/claude-code-action
  • Cloudflare APIトークンを最小権限・有効期限付きに: 現在はAccount全体権限の可能性あり、Pages:Edit と Workers Scripts:Edit に絞る
  • commit signing 有効化: GPG or SSH

P2:余裕ができたら入れたい

  • Claude Code PreToolUse hookでBashの危険コマンドブロック: cat .env系、envprintenvを防ぐ
  • Claude Code PreToolUse hookでgit commit前にgitleaks強制: コミット直前にもう一段
  • Claude Code permissionsで .env* Read拒否: 二重防御
  • eslint-plugin-no-secrets 導入: JS/TS中のリテラル検出
  • detect-secrets ベースライン化
  • Cloudflare CI連携をOIDC化: API TokenをやめてOIDC連合認証に
  • wrangler secret put運用に統一: 環境変数をWrangler Secretに集約
  • MCPサーバーのトークン棚卸し: freee、Google Workspace等
  • Claude Codeセッションログの定期ローテーション

P3:やらない/オーバーエンジニアリングと判断

  • AWS Secrets Manager等への移行: ひとりプロジェクトでCloudflareに完結している間は不要。Wrangler Secretで十分
  • Audit Log Streaming: GitHub Enterprise必須機能なので個人プランでは不可
  • EDR/MDR導入: BYOD個人PCでは過剰。Windows Defender + 定期スキャンで運用
  • GitHub Apps化: 個人プロジェクトではPATで十分

具体的な設定例

実装するときに見返す用のメモ。記事を書きながら検証していないので、導入時には公式ドキュメントを当たること。

gitleaks pre-commit hook

# Husky導入
pnpm add -D husky lint-staged
pnpm exec husky init

# .husky/pre-commit に以下を追記
gitleaks protect --staged --redact --verbose || exit 1

gitleaks バイナリは Scoop / winget / brew で入る。Windowsなら scoop install gitleaks

GitHub ActionsにgitleaksとTruffleHogを追加

# .github/workflows/security.yml
name: Security Scan

on:
  pull_request:
  push:
    branches: [master]
  schedule:
    - cron: '0 0 * * 0'  # 毎週日曜

permissions:
  contents: read

jobs:
  gitleaks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<sha>  # SHAピン留め
        with:
          fetch-depth: 0  # 全履歴スキャン用
      - uses: gitleaks/gitleaks-action@<sha>
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  trufflehog:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<sha>
        with:
          fetch-depth: 0
      - uses: trufflesecurity/trufflehog@<sha>
        with:
          extra_args: --only-verified

Claude Code PreToolUse hook(Bashの.env読み取りブロック)

.claude/settings.json に追記。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/block-env-read.mjs"
          }
        ]
      }
    ]
  }
}

.claude/hooks/block-env-read.mjs で stdin の tool_input.command を見て、cat .envenv\bprintenvgrep -r.*\.envGet-Content .env 等のパターンに該当したら exit 2 で deny。

Claude Code Read拒否

{
  "permissions": {
    "deny": [
      "Read(./apps/web/.env)",
      "Read(./apps/web/.env.*)",
      "Read(./.env)",
      "Read(./.env.*)"
    ]
  }
}

.env.example は許可したいので glob ではなく明示列挙が安全。

Cloudflareトークンの最小権限化

現在のworkflowsで使っている CLOUDFLARE_API_TOKEN は Account全体権限の可能性が高い。dashboard → My Profile → API Tokens で以下スコープに絞る:

  • AccountCloudflare Pages:Edit
  • AccountWorkers Scripts:Edit(OG Worker用)
  • IP制限はGitHub Actionsの動的IPなので不可、有効期限を90日等に

まとめ

「漏れない設計」より「漏れても被害が広がらない設計」のほうが現実的、というのが元記事の核。これは個人開発でも同じで、いま自分のリポジトリで一番抜けているのは「pre-commit/CIでの自動検出層」と「鍵の棚卸し」だった。

優先度P0の項目(GitHub Push Protection確認、gitleaks/TruffleHogでの履歴スキャン、Cloudflare/PATの棚卸し)は今日中に手を動かす。P1のhusky+gitleaksはこの週内、P2のClaude Code Hookは余裕ができたら順次入れる。

「まだやれていないことを可視化する」という意味で、この記事自体が一番役に立った。