Web app(Vue / React 系のSPA + APIサーバ)をOSSとしてGitHubに公開するとき、セキュリティ対策として何を入れておけばいいか。CodeQL や Dependabot、PR レビューのボットを入れてある人は多いが、それらは全部 CIで自動的に走る反応型 のレイヤーで、「リポ全体を観点ごとに棚卸しする」仕事は別に必要になる。
ここでこの1年で大きく変わったのが、Claude Code のOSS skillを使って手元でセキュリティ監査をかける という選択肢が現実的になったこと。CodeQLが「アラート件数」を出すのに対し、skillは「OWASP A01 観点でこのコードはこう、A02 はこう」と説明付きで返してくる。新人レビュアーを1人雇った感覚に近い。
この記事では、既存の自動レイヤー(CIで動くもの)と 手元監査レイヤー(Claude Code skill)を6つに分けて整理する。想定読者は「Web OSSを公開しているがセキュリティ周りを体系的に揃えたことはない」あたり。
6つのレイヤー
セキュリティ系のツールは大雑把に次の6層に分けて考えると整理しやすい。
| 層 | 守る対象 | 代表ツール |
|---|---|---|
| 1. 静的解析(SAST) | 自分のソースコードに潜むバグ・脆弱性 | CodeQL、Semgrep、ESLint security plugins |
| 2. 依存関係スキャン(SCA) | 使っているnpm/PyPI等パッケージのCVE | Dependabot、Socket Security、npm audit |
| 3. シークレットスキャン | 誤コミットされたAPIキー / トークン | gitleaks、GitHub secret scanning、TruffleHog |
| 4. PR bot review | 変更diffに対する第三者レビュー | CodeRabbit、Sourcery、Codex auto-review |
| 5. リポジトリ全体監査(新しい層) | OWASP Top 10 など観点ベースの棚卸し | Claude Code OSS skill 群 |
| 6. ランタイム防御 | 動いているアプリ側のXSS / CSRF / 認証 | CSP、SameSite Cookie、CSRFトークン、フレームワークの自動エスケープ |
1〜5はビルド時 / CI上で動く「コードを見るツール」。6は「アプリの実装そのもの」。両輪で初めて意味がある。
層1: 静的解析(SAST)
「コードを読むだけで分かるバグ」を機械的に拾う。GitHub Pro/Enterpriseなら CodeQL が無料で使える。.github/workflows/codeql.yml を1ファイル置くだけで、SQL injection / path traversal / プロトタイプ汚染あたりを定期スキャンしてくれる。
# .github/workflows/codeql.yml の骨子
on:
push: { branches: [main] }
pull_request: { branches: [main] }
schedule:
- cron: "0 3 * * 1" # 毎週月曜
jobs:
analyze:
uses: github/codeql-action/.github/workflows/codeql.yml@v3
with:
languages: javascript-typescript
ESLintにも eslint-plugin-security 系のpluginがあり、これは普段のlintに混ぜておくと早い段階で気付ける。
層2: 依存関係スキャン(SCA)
OSSライブラリの脆弱性は、自分のコードよりも入り口になることが多い。GitHubの Dependabot はリポジトリ設定でONにするだけで、CVEが出たパッケージにPRを自動で出してくれる。
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
Socket Security(Marketplaceアプリ)は、CVE登録前の段階のリスク — 怪しい新規メンテナ、ポストインストールスクリプトの追加、難読化コード — を見るのが強い。フリープランがあるので個人OSSでも導入しやすい。
層3: シークレットスキャン
.env や aws_secret_key = "..." をうっかりコミットしてpushしてしまった、というのを止める層。GitHubは公開リポについてはネイティブでsecret scanningを動かしている(主要プロバイダのキーは検知すると自動でrevoke候補に挙がる)。それに加えて、CIで gitleaks を一段噛ませると独自トークンや社内認証情報もカバーできる。
注意点として、gitleaks-action@v2 は v2 から Organization 所有のリポジトリでは GITLEAKS_LICENSE が必須(=有料)になっている。個人リポなら無料で動くが、会社・コミュニティ運用だとここで止まる。回避策は単純で、MIT ライセンスのまま配布されている gitleaks CLI バイナリを直接ダウンロードして走らせる。
# .github/workflows/secret-scan.yml の骨子
- uses: actions/checkout@v6
with:
fetch-depth: 0 # full history scan needs every commit
- name: Install gitleaks
env:
GITLEAKS_VERSION: 8.30.1
# SHA256 は GitHub Releases の checksums から取る。
# バージョンを上げたら必ず一緒に更新する。
GITLEAKS_SHA256: 551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb
run: |
set -euo pipefail
ARCHIVE="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
curl -sSfL -o "$ARCHIVE" \
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/${ARCHIVE}"
echo "${GITLEAKS_SHA256} ${ARCHIVE}" | sha256sum -c -
sudo tar -xz -C /usr/local/bin -f "$ARCHIVE" gitleaks
- name: Run gitleaks (full history scan)
run: gitleaks detect --source . --redact --verbose --exit-code 1
ポイントは fetch-depth: 0 で全履歴を取ること(過去コミットの誤コミットも検知するため)と、バイナリのSHA256をワークフローに書いて改ざん検知を入れること。詳しい経緯と落とし穴は別記事 GitHub Actions に gitleaks(CLI 版)を入れた話 に書いた。
層4: PR bot review
PRが立つと自動でレビューコメントを書く外部のbot。観点と粒度が違うので、複数併用しても意外と被らない。
| bot | 得意 |
|---|---|
| CodeRabbit | 全体構成、API矛盾、テスト不足の指摘 |
| Sourcery | 命名 / 関数分割 / TypeScript的な型の絞り込み |
どちらも GitHub Marketplace アプリで、リポ単位で有効化すればすぐ動く。両方並べても観点が違うので意外と被らない。OSSプランは無料 or 低額で、小〜中規模リポなら個人 / 小規模チームでも無理なく入れられる。
層5: リポジトリ全体の観点監査 — Claude Code OSS skill
ここがこの1年で増えた層。bot review(層4)はあくまで diff 反応型で、半年前に書かれた v-html のソースが今でも信用できる経路か、みたいな疑問は拾えない。OWASP Top 10 のようなチェックリストに対してリポ全体を一度フラットに監査する仕事は、別レイヤーで必要になる。
主要なOSS skill:
| skill | 守備範囲 |
|---|---|
| anthropics/claude-code-security-review | Anthropic公式。PR差分をXSS / SQL injection等で自動レビューするGitHub Action |
| agamm/claude-code-owasp | OWASP Top 10:2025 + ASVS 5.0 + Agentic AI security + 20言語のquirks |
| trailofbits/skills | Trail of Bits製の脆弱性検出・監査ワークフロー集 |
| VicKayro/claude-security-audit | OWASP + headers + auth + paywall + infraまで16セクションの横断監査 |
| Security-Phoenix-demo/security-skills-claude-code | DevSecOps統合(SAST/DASTパイプラインへの組み込み側) |
| Eyadkelleh/awesome-claude-skills-security | pentesting / CTF寄り(攻撃側payload集、自リポ防御には基本不要) |
カタログとしては BehiSecc/awesome-claude-skills が見やすい。
Claude Code skill系の良さは、観点を日本語/英語のチェックリストとして実装してある点。CodeQLが「アラート〇〇件」を出すのに対し、「A01 Broken Access Control の観点、このリポではこう」という形で説明付きレポートになる。新人にレビューさせる代わりに走らせる感覚に近い。
層6: アプリ実装側のランタイム防御
ここはツールで自動検知する話ではなく、自分でコードをそう書くしかない領域。フレームワークが提供しているデフォルトに乗りつつ、危ない部分は明示的にレビューしていく。Vue / React frontendに絞ると、繰り返し問われる典型は以下:
- XSS: フレームワークの自動エスケープに乗る。Vueの
v-html/ ReactのdangerouslySetInnerHTMLは どうしても必要なときだけ、入力源を文書化して使う。Markdownレンダラを通す場合は DOMPurify などのサニタイザを噛ます。 - CSP(Content Security Policy): HTTPヘッダで
default-src 'self'ベースを敷き、inline scriptを禁じる。アプリのリスクが一段下がる。 - クリックジャック対策:
X-Frame-Options: DENYまたは CSP のframe-ancestors 'none'。 - CSRF: SameSite Cookie(
SameSite=Laxがデフォルト推奨)+ サーバ側のトークン検証。 target="_blank"のnoopener漏れ: 自動でnoopener noreferrerを付ける。タブナビング攻撃を防ぐ。- postMessage:
addEventListener('message', ...)で受けるなら、必ずevent.originをホワイトリスト検証。 - トークン保管場所より、XSSを起こさないことが本丸:
localStorageがJSから読める一方で HttpOnly Cookie はJSから読めない、という違いはあるが、XSSが入った時点で攻撃者はfetch(..., { credentials: 'include' })でCookieを「使う」ことができる(読めなくてもサーバには自動で送られる)。つまりトークンの置き場所の議論より先に、そもそもXSSを発生させないことが本質。HttpOnly + SameSiteは「漏洩経路を狭める」副次的な対策と捉える。 - 依存ライブラリのバージョンpin: lockfileをコミット、Dependabot で計画的に上げる(自動マージは慎重に)。
参考文献
体系的に身につけたいときの参照先。一度通しで読むと、コードレビューのときに違和感を持てる範囲がだいぶ広がる。
- OWASP Cheat Sheet Series — XSS / CSRF / Cookie / CSP / Authentication など、観点別に短くまとまっている公式リファレンス。
- OWASP Top 10:2025 — 何が「いま」よく狙われるかの俯瞰。各カテゴリに具体例とリンク。
- MDN: Content Security Policy (CSP) — CSPの基本と各ディレクティブの解説。実装前に一読推奨。
- MDN: SameSite cookies —
Lax/Strict/Noneの違いとCSRFとの関係。 - Vue.js Security Best Practices(公式) —
v-html/ template injection / URL bindingの注意点。 - React Docs: JSX prevents Injection Attacks —
dangerouslySetInnerHTMLの使い方と注意。 - DOMPurify —
v-html/dangerouslySetInnerHTMLをどうしても使う場合の標準サニタイザ。 - Web Security Academy(PortSwigger) — 無料の脆弱性学習ラボ。手を動かしながら脅威モデルを身につけるのに向いている。
入れる順番
全部いきなりは無理だ。優先度を付けるなら次の順になる。
- 依存関係スキャン(層2)を有効化 — Dependabot は1ファイル / Socket Security は GitHub Apps から1クリック。一番投資対効果が高い。
- シークレットスキャン(層3) — gitleaks の CLI 版を CI に置く。歴史的な誤コミットも遡って検知する。
- 静的解析(層1)の CodeQL — workflowを1つ追加。週次でいい。
- bot review(層4)を1つだけ — まずCodeRabbitかSourceryから。両方並べるのは慣れてから。
- 層5 のskill を1つ手元で叩いてbaseline化 —
agamm/claude-code-owaspをローカルで1回走らせ、結果をSECURITY.mdに転記。許容 / 直す / defer を仕分け。この記事の本題はここ。 - 層6 の実装側ベストプラクティス — コードレビューの目線として身につける。
1〜4はGitHub側の設定 / CIワークフローを足すだけで済む「置けば動く」系で、ハマりどころが少ない。5は 自分のターミナルでClaude Code を起動して、skillを実行して、レポートを読む という能動的な作業になる。最初は半日ぐらいかかるが、見えるものは段違いに多い。
手元監査の具体的な流れ
層5の agamm/claude-code-owasp を例にとると、手順はだいたい以下:
# 1. リポを clone(or 既にある場合はそのディレクトリへ)
cd path/to/your-repo
# 2. skill を取ってくる(marketplace 経由 / 直接 clone のいずれか)
# 詳細は各skillの README に従う
# 3. Claude Code を起動して skill を呼ぶ
claude
> /claude-code-owasp
skillが OWASP A01 〜 A10 を順に質問し、該当コードを探して、見つけた箇所を引用付きで返してくる。フォールスポジティブはその場で「これは意図通り」と返事すれば次に進む。レポートが揃ったら SECURITY.md か docs/security-audit.md に貼り付けて、issue化するもの / 様子見するものに仕分ける。これでリポ全体の 観点別ベースライン が初めて手に入る。
bot reviewと違って、この監査は 新規コードに対する反応ではなく、既存コード全体に対する点検だ。年に2〜4回ぐらいの頻度で回せば十分機能する。
注意
- LLMにOSSリポを丸ごと読ませる以上、外部APIにコードを送ることになる。プライベートリポや顧客コードで使う場合は、モデル提供者の利用規約とログ保持ポリシーを確認すること。公開OSSなら問題ない。
- bot reviewのコストは規模次第。2つ並走の運用感覚としては、小〜中規模OSS(数百PR/年)で月数ドル程度に収まることが多い。
- CodeQLとClaude Code skillの守備範囲は重なるが、CodeQLは脆弱性パターンの機械検出、skillは観点ベースのチェックリストと説明、という違いがある。両方あって損はない。
- skillは活発に更新中で、
SKILL.mdのフォーマットや呼び出し方が変わる可能性がある。フォーク or@<sha>固定したい場合は各リポのREADMEを確認。
締め
CIで自動的に走る「反応型」のレイヤー(CodeQL / Dependabot / gitleaks / bot review)を揃えるところで止まっていた人にとって、Claude Code skill で手元から能動的に監査する という第5レイヤーが現実的な選択肢になったのがこの1年の大きな変化だと思う。半日かけてベースラインを取ると、自分のリポでいま何が論点なのかが急にはっきり見える。agamm/claude-code-owasp あたりから入って、年に何回か回す習慣をつけるのを薦めたい。