個人開発で MathDesk という教育アプリを作っている。Claude Code で開発し、GitHub の private リポで管理している。
セキュリティは「まあ private だし」で放置していた。GlassWorm を調べたら、その前提が崩れた。
きっかけ
2026年3月、GlassWorm というサプライチェーン攻撃が話題になっていた。Claude Code に「glass worm等のホットなセキュリティリスクたちと現在有用なセキュリティ構築について調査して」と投げた。
返ってきた内容が重かった。VS Code 拡張を偽装して開発者の環境に入り込み、不可視の Unicode 文字にペイロードを隠し、Solana ブロックチェーンを C2 に使うのでテイクダウンできない。被害者のトークンを盗んで別のパッケージや拡張を自動で汚染する自己増殖型。900万インストール以上が影響を受けたとされている。
同時期に ForceMemo という攻撃も進行中で、盗んだ GitHub トークンで Python リポに force-push して履歴を書き換える。元のコミットメッセージと著者を保持するので GitHub の UI では気づけない。
Claude Code 自体にも Critical の RCE 脆弱性(CVE-2026-31862)が見つかっている。設定ファイル経由で任意コマンドを実行できる。AI エージェントのスキル定義3行で SSH 鍵を窃取できるという報告もある(Snyk ToxicSkills 調査)。
「何かオールインクルーシヴないの?」
調査結果を読んで、私が聞いたのがこれだった。「何かオールインクルーシヴで個人で対応できる範囲のものないの? クローボット周辺とかになんかありそうだけど(それ自体も汚染されてるパラドックスもありそうだが」
Claude Code が返した答えは「単一のオールインワン製品は存在しない」。GlassWorm 自体が VS Code 拡張(開発者ツール)を偽装して入り込んだ事実は、「守るためのツール自体が攻撃ベクターになる」が理論ではなく現実であることを証明していた。
Socket Firewall Free というパッケージプロキシを提案された時に「これPip uv やwingetなどはどうなるん? なんか的外れなこと言ってる?」と聞いた。的外れではなかった。pip と uv は対応していたが、winget や VS Code 拡張は守備範囲外だった。npm/PyPI(言語レジストリ)、winget(OS レジストリ)、VS Code Marketplace(IDE エコシステム)は信頼チェーンが別物なので、一つのプロキシで全部は守れない。
自分のリポを監査してみた
ここまで調べて「じゃあ自分は大丈夫なのか」と思い、Claude Code に全リポの監査を投げた。17個の GitHub リポを調べた結果:
- public リポ(portal)の Secret Scanning と Push Protection が全無効だった。 Public なのに
- 17リポ中16リポに Dependabot が未設定。 依存関係の脆弱性チェックが動いていない
- VS Code 拡張は17個、全て大手パブリッシャーか自作。 ここは無事だった
- Claude Code の設定に
ANTHROPIC_BASE_URLの改竄はなし。(CVE-2026-21852 で攻撃ベクターになる)
そしてローカルで gitleaks を走らせたら、git 履歴から5件のシークレットが見つかった。
「それ、けっこうやばいな・・・」
5件のうち1件は Firebase の API キーで、過去にポストモーテムまで書いたリーク事故のキーがまだ有効なまま git 履歴に残っていた。
GCP Console で確認したら、そのキーはアクティブのまま放置されていた。Firebase 自体も「停止はしてないはず、放置」という状態。使っていないのに有効なキーが漏洩済みの git 履歴にある。
キーをローテーションし、.gitleaks.toml で過去コミットを allowlist に追加した。git 履歴からシークレットを消す方法(git filter-repo)もあるが、全コミットハッシュが変わるのでリスクが高い。キーを無効化済みなら allowlist で十分、というのが業界のコンセンサスらしい。
コーダー負担をゼロにする設計
対策を組み始めた時に私が気にしたのは「これの導入によってコーダーのコンテキスト負担はどの程度か(できればコーダーはなにも負担なくてその外部が保護するのがよいが」ということ。
Claude Code が各対策のコーダー負担を正直に分類した:
- GitHub の設定(Secret Scanning、Push Protection、Dependabot、Branch Protection、CI)→ 全部バックグラウンドで動く。ゼロ
- Socket Firewall Free →
npm installのたびにsfwを付ける必要がある。 ただし shell alias で透過的にすれば負担ゼロ - Gitsign(コミット署名)→ コミットごとにブラウザで OIDC 認証。最も重い
- gitleaks pre-commit hook → 普段は透明だが誤検知でコミットが中断する
この分析を見て方針を決めた。コーダーの日常ワークフローを変えない。 Gitsign は見送り、代わりに Branch Protection で force-push を構造的に禁止する。gitleaks pre-commit も見送り、Push Protection + CI の gitleaks で同じ範囲をカバーする。
GitHub Free の private リポは丸裸
Branch Protection を設定しようとして、Claude Code が「MathDesk(private)に Branch Protection を設定できない — GitHub Free プランでは private リポの branch protection は利用不可」と報告してきた。
これが今回一番驚いたこと。GitHub Free の private リポは force-push し放題で、CI が失敗しても main に直接 push できる。ForceMemo 攻撃がトークンを盗んだら、やりたい放題ということ。
「じゃあまあ有料プランにするわさすがに4ドルくらいはらう もっとたかいかとおもってた」。GitHub Pro にアップグレードして、5リポに Branch Protection を設定した。force-push 禁止、PR 必須、CI 必須、管理者も迂回不可。
CI が通るまでの試行錯誤
gitleaks + OSV-Scanner + Semgrep の3ジョブを GitHub Actions に入れた。全部 fail した。
gitleaks-action@v2は有料ライセンスが必要だった → CLI 直接実行に変更google/osv-scanner-action@v2のパスが間違っていた →go install+ CLI に変更- Semgrep の
--errorフラグが既存コードの40件の findings を全てブロックしていた → 除去
4回目の push でようやく全 pass。gitleaks が git 履歴のシークレット5件を検出して fail していたのが最後の壁で、これは先述のキーローテーション + allowlist で解消した。
Dependabot が早速仕事をした
Dependabot を有効化した途端、31件の脆弱性(1 critical, 16 high, 11 moderate, 3 low)が報告された。放置していたツケ。
Dependabot の自動 PR 10件と npm audit fix で critical / high は全て解消した。残り16件は全て間接依存の上流修正待ちで手出しできない。@modelcontextprotocol/sdk が hono に依存していて、firebase-admin が undici に依存している。これらはツールでは解決できない。
chezmoi リポも守った
.bashrc に sfw の alias を追加した後、ふと chezmoi(dotfiles 管理)のリポを確認したら Branch Protection なし、force-push し放題だった。chezmoi リポには CLAUDE.md(AI の行動ルール)、メモリファイル、スキル定義が入っている。改竄されると開発環境そのものが汚染される。
force-push 禁止だけ設定した。PR 必須にすると chezmoi の直接 push ワークフローが壊れるので、そこはトレードオフ。
やったことの全体像
| 対策 | コスト | コーダー負担 |
|---|---|---|
| Secret Scanning + Push Protection | 無料 (public) | ゼロ |
| Branch Protection(5リポ) | $4/月 (Pro) | ゼロ |
| CI(gitleaks / OSV-Scanner / Semgrep) | 無料 | ゼロ |
| Dependabot alerts + version updates | 無料 | ゼロ(PR が来る) |
| VS Code extensions.allowed | 無料 | 初回のみ |
| sfw alias(npm/pip/uv) | 無料 | ゼロ(alias 後) |
| GCP API キーのローテーション | — | — |
| 許可リスト棚卸し(210→160件) | — | — |
守れないもの
- Private リポの Secret scanning — Pro でも別途 $19/月が必要
- 許可済みパブリッシャーの拡張汚染 — GlassWorm のアカウント乗っ取り型には extensions.allowed が効かない。VS Code にサンドボックスが実装されるまで構造的に無理。Zed は WASM サンドボックスで先行しているが、エコシステムの移行コストが高い
- 間接依存の脆弱性 — npm audit fix で消えない。上流の修正待ち
- AI エージェント経由のプロンプトインジェクション — CI では検出できない
具体的な設定手順
設定ファイルのコピペ手順、Windows での各ツールの動作状況は Zenn 側の記事にまとめた。
→ AIエージェント時代の個人リポ防御ガイド — GitHub・npm・VS Code拡張(2026年3月調査・実装)
この記事を書いた理由
自分の環境が丸裸だったので対策を組んだが、これが最善かどうかはわからない。「ここはこうしたほうがいい」「このツールのほうが良い」という知見があれば教えてほしい。
この記事の調査・対策実施・執筆は Claude Code(Opus 4.6)が行い、私が方針判断と承認を担当した。