frontend-review-security について
フロントエンドのコードと設定を調べるチーム向けに、セキュリティレビューの手順を示すスキルです。静的なリスク、認証・認可、攻撃シナリオの机上確認、staging の点検を扱い、レビュー報告を作成します。
主な機能
- 01危険な HTML 注入箇所の確認
- 02トークン保存と認証のレビュー
- 03環境変数や設定の露出確認
- 04一般的な攻撃シナリオの机上確認
- 05staging チェックリストと報告書の作成
活用シーン
- 01フロントエンドのトークン保存とルートガードの確認
- 02クライアントバンドル内の機密環境変数の検出
- 03staging の手動セキュリティ確認項目の準備
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mizchi/ skills --skill frontend-review-securityインストール後、Claude Code で/frontend-review-securityを入力して読み込まれたか確認します。
同梱ファイルREADME.md
詳細
フロントエンドレビュー — セキュリティ
フロントエンドのセキュリティレビューを実施します。重点項目は次のとおりです。
- 静的解析 — リスクのある HTML シンク、クライアントバンドルでの環境変数の露出
- 認証/認可 — トークンの保存、ルートガード、セッション管理
- AI セルフペンテスト — 一般的な脆弱性パターンの机上確認
- ステージング環境 — HTTP ヘッダー、認証境界、Cookie フラグ
手順
scripts/audit-security.sh --repo <client-repo>を実行します。raw/security.jsonを読みます。dangerouslySetInnerHTML/v-html/.innerHTML =が検出された箇所について、該当ファイルを特定し、入力がサニタイズされているか判断します。- 認証と認可のレビューを実施します(以下を参照)。
- 環境変数/設定のレビューを実施します(以下を参照)。
- AI セルフペンテストでは、以下の攻撃シナリオを頭の中で順に確認します。
- ステージング環境では、ヘッダーのチェックリストを作成します。
認証と認可のレビュー
トークンの保存
アクセストークンの保存場所を確認し、安全でないパターンにはフラグを立てます。
| 保存場所 | リスク | 判定 |
|---|---|---|
httpOnly Cookie | JavaScript からアクセスできず、XSS に耐性がある | ✅ 推奨 |
localStorage | ページ上のあらゆる JavaScript から読み取り可能 — XSS により盗まれる | ⚠ フラグを立て、XSS 対策を必須とする |
sessionStorage | localStorage と同じ XSS リスクがある | ⚠ フラグを立てる |
| メモリ内(モジュール変数) | 再読み込みで失われる。短命な SPA でのみ実用的 | 状況による |
- リフレッシュトークンも
httpOnlyCookie に保存されているか確認します。 - アクセストークンの有効期間が短いか確認します(推奨:15 分~1 時間)。
ルートガード
ProtectedRoute(または同等のもの)に、認証状態が確定する前に保護対象ページが一瞬表示されるのを防ぐローディング状態がありますか?
// Bad: no loading state — redirects to /login during initial auth check
if (!user) return <Navigate to="/login" />;
// Good: loading state prevents flash
if (isLoading) return <LoadingSpinner />;
if (!user) return <Navigate to={`/login?redirect=${encodeURIComponent(location.pathname)}`} />;
- ログイン後に元のページへリダイレクトされますか(
redirect/redirect_toパラメーター)? - 保護対象の API エンドポイントすべてにサーバー側の認可が実装されていますか — フロントエンドのガードだけでは、DevTools や curl で回避できます。
トークンの更新
- API クライアントは、401 を受け取るとトークンを先に更新してから自動再試行しますか?
- 並行して発生した 401 によって複数の更新リクエストが実行されないよう、更新処理は重複排除されていますか?
let refreshPromise: Promise<string> | null = null;
async function refreshToken(): Promise<string> {
if (refreshPromise) return refreshPromise;
refreshPromise = doRefresh().finally(() => { refreshPromise = null; });
return refreshPromise;
}
ログアウト
- ログアウト時にサーバーのエンドポイントを呼び出し、かつクライアント側の状態をすべてクリアしますか?
// Required logout sequence:
await api.post('/auth/logout'); // revoke server-side session
queryClient.clear(); // clear TanStack Query cache
authStore.reset(); // clear Zustand / Jotai auth atoms
router.replace('/login'); // navigate away before clearing is dangerous
- ログアウト後、ページを完全に再読み込みすると前のユーザーのデータが表示されますか?(確認箇所:TanStack Query の開発者ツール、React の状態、localStorage)
環境変数/設定のレビュー
VITE_/NEXT_PUBLIC_を接頭辞とする変数にシークレットを含めてはいけません。 Vite/Next.js はこれらをクライアントバンドルに埋め込むため、DevTools で誰でも読み取れます。.envをコミットしてはいけません。 次を実行します:git log --all --full-history -- '*.env'- 環境変数の読み取りは、
src/config.ts(または同等のもの)が唯一のエントリーポイントになっていますか? コンポーネント内にimport.meta.env.VITE_FOOの直接呼び出しが散在している場合は、レビュー上の警告事項です。 - 必須の環境変数がない場合、
config.tsは起動時にエラーをスローしますか?
// config.ts — startup-time validation
const requireEnv = (key: string): string => {
const value = import.meta.env[key];
if (!value) throw new Error(`Missing required env var: ${key}`);
return value;
};
- 不明な
VITE_*キーを TypeScript で検出できるよう、vite-env.d.tsでImportMetaEnvを拡張していますか?
AI セルフペンテストのシナリオ
各シナリオを頭の中で順に確認し、結果を「問題なし/指摘事項/判断不能」で記録します。
- URL パラメーター経由の XSS — 悪意のある
?q=<script>alert(1)</script>がサニタイズされずに表示されますか? - フォーム入力経由の XSS — ユーザーが入力した HTML がサニタイズされずに
dangerouslySetInnerHTMLで表示されることはありますか? - CSRF — 状態を変更する API 呼び出しに CSRF トークンが必要ですか、または
SameSite=StrictCookie を使用していますか? - 認証境界の回避 — 認証されていない状態で
fetch('/api/protected')を実行すると、データが返されますか? - ストレージ内の機密データ —
localStorage.getItemによってトークン、PII、またはセッションデータが明らかになりますか? - クライアント側のみの認可 — React コードにロールチェックがあり、サーバー側では同等のチェックが行われていない箇所はありますか?
- オープンリダイレクト — ログイン時の
redirect/nextパラメーターで、任意の外部 URL を指定できますか?
ステージングチェックリスト
デプロイ済みのステージング URL に対して人間が実行するため、以下を作成します。
-
Content-Security-Policyヘッダーが設定され、制限的である -
max-age ≥ 31536000を指定したStrict-Transport-Security(HSTS) -
X-Frame-Options: DENYまたはSAMEORIGIN -
X-Content-Type-Options: nosniff - Cookie に
Secure、HttpOnly、SameSite=Strict(またはLax)が設定されている - 有効なセッションなしで
GET /api/meを実行すると、ユーザーデータではなく 401 が返る - 一般ユーザーとして
GET /api/admin-onlyを実行すると、データではなく 403 が返る
出力
<client-repo>/.frontend-review/report/latest/md/security-review.md に以下を記述します。
- 静的解析での指摘事項(リスクのあるシンク、環境変数の露出)
- 認証/認可に関する指摘事項(トークンの保存、ルートガードの不備、ログアウトの問題)
- AI ペネトレーションテストのメモ(各シナリオ:OK/指摘事項あり/判定不能)
- ステージングチェックリスト(人間が実行する項目)
- 起票する Issue(タイトルと本文を指定した
gh issue createコマンド)
gh issue create コマンドは実行しないでください。人間が実行できるように表示してください。
範囲
- 実際のエクスプロイトは試みないでください。これは机上レビューです。
- 本番 URL に対してスキャナーを実行しないでください。
- クライアントのソースコードには手を加えないでください。
- CVE のトリアージとトレンド監視は
frontend-review-depsが担当します。
参考資料
- チェックリスト:
10-security.md、25-auth-authorization.md、26-env-config.md - フェーズ:
week-3-security-vrt.md - OWASP:https://owasp.org/www-project-top-ten/
コメント
Markdown 対応