mcpField
S
supabase-extract-anon-key

supabase-extract-anon-key

github.com/yoanbernabeuセキュリティ71487 回インストール39 週間前に更新
リポジトリ

supabase-extract-anon-key について

クライアント側コードから Supabase の anon 公開 API キーを抽出する監査スキルです。一般的なコードや環境変数のパターンを検索し、JWT の内容を検証して結果を逐次記録します。

主な機能

  1. 01クライアント側コードから anon キーを検索
  2. 02クライアント初期化と環境変数のパターンを確認
  3. 03JWT 形式、ロール、プロジェクト参照を検証
  4. 04キーの出所を記録し証拠を保存
  5. 05コンテキストと監査ログを逐次更新

活用シーン

  1. 01Supabase API 監査に必要な anon キーを取得
  2. 02クライアントコードに誤った種類のキーが露出していないか確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/yoanbernabeu/supabase-pentest-skills --skill supabase-extract-anon-key

インストール後、Claude Code で/supabase-extract-anon-keyを入力して読み込まれたか確認します。

詳細

Supabase Anon Key の抽出

🔴 重大:コンテキストファイルの段階的な更新が必須です

コンテキストファイルには、最後にまとめてではなく、作業を進めながら必ず書き込んでください。

  • 発見のたびに、直ちに .sb-pentest-context.json に書き込んでください
  • 各アクションの前後に .sb-pentest-audit.log に記録してください
  • スキルの完了までファイルの更新を待たないでください
  • スキルがクラッシュしたり中断されたりした場合でも、それまでの調査結果がすべて保存されている必要があります

これは任意ではありません。段階的に書き込まないことは重大なエラーです。

このスキルは、クライアント側のコードから Supabase の匿名(公開)API キーを抽出します。

このスキルを使用するタイミング

  • Supabase URL の抽出後、テスト用の API キーを取得するとき
  • anon キーのみが公開されており、service キーは公開されていないことを確認するとき
  • 認証が必要な API 監査スキルを実行する前

前提条件

  • Supabase URL が抽出済みであること(または supabase-extract-url を自動的に呼び出すこと)
  • 対象アプリケーションにアクセスできること

Anon キーについて

anon キー(公開キーとも呼ばれます)は次のとおりです。

  • ✅ クライアント側のコードに含まれていることが想定されています
  • ✅ RLS(行レベルセキュリティ)が適切に設定されていれば安全です
  • ⚠️ RLS が未設定、または誤って設定されている場合はリスクがあります
  • ❌ service_role キーとは異なります(クライアント側のコードに含めては絶対にいけません)
キーの形式

Supabase の anon キーは JWT です。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFiYzEyMyIsInJvbGUiOiJhbm9uIiwiaWF0IjoxNjQwMDAwMDAwLCJleHAiOjE5NTUzNjAwMDB9.xxxx

キーの特徴:

  • eyJ で始まります({"alg": を Base64 エンコードしたもの)
  • ペイロードに "role":"anon" が含まれます
  • "ref" クレームにプロジェクトの参照情報が含まれます

抽出パターン

このスキルでは、次のパターンを検索します。

1. キーの直接代入
const SUPABASE_KEY = 'eyJhbGci...'
const SUPABASE_ANON_KEY = 'eyJhbGci...'
2. クライアントの初期化
createClient(url, 'eyJhbGci...')
createClient(url, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY)
3. 環境変数のパターン
NEXT_PUBLIC_SUPABASE_ANON_KEY
VITE_SUPABASE_ANON_KEY
REACT_APP_SUPABASE_KEY
SUPABASE_KEY

使用方法

基本的な抽出
Extract Supabase anon key from https://myapp.example.com
URL がすでにわかっている場合
Extract anon key for project abc123def

出力形式

═══════════════════════════════════════════════════════════
 ANON KEY EXTRACTED
═══════════════════════════════════════════════════════════

 Key Type: anon (public)
 Severity: ℹ️  Expected (verify RLS configuration)

 Key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJz
      dXBhYmFzZSIsInJlZiI6ImFiYzEyM2RlZiIsInJvbGUiOiJhbm
      9uIiwiaWF0IjoxNjQwMDAwMDAwLCJleHAiOjE5NTUzNjAwMDB9
      .xxxxxxxxxxxxx

 Decoded Payload:
 ├── iss: supabase
 ├── ref: abc123def
 ├── role: anon
 ├── iat: 2021-12-20T00:00:00Z
 └── exp: 2031-12-20T00:00:00Z

 Found in:
 └── /static/js/main.js (line 1253)
     createClient('https://abc123def.supabase.co', 'eyJhbGci...')

 Next Steps:
 ├── Run supabase-audit-rls to test if RLS protects your data
 ├── Run supabase-audit-tables-read to see what's accessible
 └── Run supabase-extract-service-key to check for critical leaks

 Context updated: .sb-pentest-context.json
═══════════════════════════════════════════════════════════

キーの検証

このスキルでは、抽出したキーを検証します。

Validation:
├── Format: ✅ Valid JWT structure
├── Decode: ✅ Payload readable
├── Role: ✅ Confirmed "anon" role
├── Project: ✅ Matches extracted URL (abc123def)
└── Expiry: ✅ Not expired (expires 2031-12-20)

複数のキー

複数のキーが見つかった場合:

═══════════════════════════════════════════════════════════
 MULTIPLE KEYS FOUND
═══════════════════════════════════════════════════════════

 ⚠️  2 potential Supabase keys detected

 1. Anon Key (confirmed)
    └── Role: anon, Project: abc123def

 2. Unknown Key
    └── Role: service_role ⚠️  SEE supabase-extract-service-key
        This may be a CRITICAL security issue!

═══════════════════════════════════════════════════════════

コンテキスト出力

.sb-pentest-context.json に保存されます。

{
  "supabase": {
    "anon_key": "eyJhbGci...",
    "anon_key_decoded": {
      "iss": "supabase",
      "ref": "abc123def",
      "role": "anon",
      "iat": 1640000000,
      "exp": 1955360000
    },
    "anon_key_sources": [
      {
        "file": "/static/js/main.js",
        "line": 1253
      }
    ]
  }
}

セキュリティ評価

検出事項重大度説明
クライアント側の anon キーℹ️ 情報想定される状態ですが、RLS をテストしてください
期限切れの anon キー⚠️ P2キーをローテーションしてください
複数の anon キー⚠️ P2キーのローテーションに問題がある可能性があります
ロールが "anon" ではない🔴 P0誤った種類のキーが公開されています!

よくある問題

❌ 問題: キーが見つかったものの、デコードできない ✅ 解決策: 難読化または分割されている可能性があります。次を試してください。

Extract anon key with deobfuscation from https://myapp.example.com

❌ 問題: キーが URL のプロジェクトと一致しない ✅ 解決策: アプリが複数の Supabase プロジェクトを使用している可能性があります。両方のキーが記録されます。

❌ 問題: Supabase が検出されたのに、キーが見つからない ✅ 解決策: キーが実行時に取得されている可能性があります。ネットワークリクエストを確認してください。

Monitor network for anon key on https://myapp.example.com

ベストプラクティスに関する注意

このレポートを読む開発者向け:

  1. クライアント側に anon キーがあるのは通常のことです — そのように設計されています
  2. RLS は非常に重要です — anon キーのセキュリティは RLS に依存します
  3. クライアント側で service_role を使用しないでください — 代わりに Edge Functions を使用してください
  4. キーを定期的にローテーションしてください — Supabase Dashboard で実行できます

必須:コンテキストファイルの段階的な更新

⚠️ このスキルでは、最後にまとめてではなく、実行中に追跡ファイルを段階的に更新する必要があります。

重要なルール:作業を進めながら書き込む

すべての書き込みを最後にまとめるのはやめてください。代わりに、次の手順で進めます。

  1. アクションを開始する前に → .sb-pentest-audit.log にアクションを記録します
  2. 発見のたびに → 直ちに .sb-pentest-context.json を更新します
  3. 重要な手順のたびに → .sb-pentest-audit.log に完了を記録します

これにより、スキルが中断、クラッシュ、またはタイムアウトした場合でも、それまでの調査結果がすべて保持されます。

必須のアクション(段階的に実施)
  1. 抽出したデータを .sb-pentest-context.json に更新します。

    {
      "supabase": {
        "anon_key": "eyJhbGci...",
        "anon_key_decoded": { ... },
        "anon_key_sources": [ ... ]
      }
    }
    
  2. .sb-pentest-audit.log に記録します。

    [TIMESTAMP] [supabase-extract-anon-key] [START] Beginning anon key extraction
    [TIMESTAMP] [supabase-extract-anon-key] [SUCCESS] Anon key extracted
    [TIMESTAMP] [supabase-extract-anon-key] [CONTEXT_UPDATED] .sb-pentest-context.json updated
    
  3. ファイルが存在しない場合は、書き込み前に作成します。

コンテキストファイルを更新しないことは許容されません。

必須:証拠の収集

📁 証拠ディレクトリ: .sb-pentest-evidence/02-extraction/

作成する証拠ファイル
ファイル内容
extracted-anon-key.jsonデコードされた JWT ペイロードを含む anon キー
証拠の形式
{
  "evidence_id": "EXT-ANON-001",
  "timestamp": "2025-01-31T10:07:00Z",
  "category": "extraction",
  "type": "anon_key",
  "severity": "info",

  "key_data": {
    "key_prefix": "eyJhbGciOiJIUzI1NiI...",
    "key_suffix": "...xxxx",
    "full_key_length": 256
  },

  "decoded_payload": {
    "iss": "supabase",
    "ref": "abc123def",
    "role": "anon",
    "iat": "2021-12-20T00:00:00Z",
    "exp": "2031-12-20T00:00:00Z"
  },

  "source": {
    "file": "/static/js/main.js",
    "line": 1253,
    "context": "createClient('https://abc123def.supabase.co', 'eyJhbGci...')"
  },

  "validation": {
    "format_valid": true,
    "role_confirmed": "anon",
    "project_matches": true,
    "expired": false
  }
}

関連スキル

  • supabase-extract-url — まず URL を取得します(必要に応じて自動的に呼び出されます)
  • supabase-extract-service-key — 重大な service キーの漏えいを確認します
  • supabase-audit-rls — RLS がデータを保護しているかテストします
  • supabase-audit-tables-read — このキーでアクセスできるデータを確認します

コメント