supabase-audit-tables-list について
Supabase PostgREST API で公開されるデータベーステーブルを調べる監査スキルです。OpenAPI スキーマからテーブルや列を列挙し、スキーマの公開状況とリスクを確認して結果を逐次記録します。
主な機能
- 01PostgREST の OpenAPI スキーマからテーブルを列挙
- 02スキーマと列の詳細を収集
- 03非公開スキーマの公開状況を確認
- 04テーブルを想定リスク別に分類し証拠を保存
- 05コンテキストと監査ログを逐次更新
活用シーン
- 01RLS ポリシーの検査前に API の攻撃対象領域を把握
- 02プロジェクトで公開されているテーブルとスキーマを監査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yoanbernabeu/ supabase-pentest-skills --skill supabase-audit-tables-listインストール後、Claude Code で/supabase-audit-tables-listを入力して読み込まれたか確認します。
詳細
公開テーブルの一覧
🔴 重大:コンテキストファイルを段階的に更新する必要があります
コンテキストファイルには、最後にまとめてではなく、作業を進めながら必ず書き込んでください。
- 発見するたびに、
.sb-pentest-context.jsonに直ちに書き込んでください- 各アクションの前後に
.sb-pentest-audit.logに記録してください- スキルの完了までファイルの更新を待たないでください
- スキルがクラッシュまたは中断された場合でも、それまでの調査結果がすべて保存されている必要があります
これは任意ではありません。段階的な書き込みを行わないことは重大なエラーです。
このスキルは、Supabase PostgREST API を通じて公開されているすべてのデータベーステーブルを検出します。
このスキルを使用する場面
- API の攻撃対象領域を把握する場合
- RLS ポリシーをテストする前
- 公開されているデータモデルを一覧化する場合
- 包括的なセキュリティ監査の一環として
前提条件
- Supabase URL が抽出済み(必要に応じて自動で呼び出されます)
- Anon key が抽出済み(必要に応じて自動で呼び出されます)
仕組み
Supabase は、以下の PostgREST を通じてテーブルを公開します。
https://[project-ref].supabase.co/rest/v1/
このスキルは、OpenAPI スキーマエンドポイントを使用してテーブルを列挙します。
https://[project-ref].supabase.co/rest/v1/?apikey=[anon-key]
公開されるもの
デフォルトでは、Supabase は public スキーマ内のテーブルを公開します。テーブルが公開されるのは、次の条件を満たす場合です。
- 公開対象のスキーマ(デフォルト:
public)に存在する - 明示的な
REVOKEが実行されていない - PostgREST から参照できる
使用方法
基本的なテーブル一覧
List tables exposed on my Supabase project
スキーマ情報付き
List all exposed tables with column details
出力形式
═══════════════════════════════════════════════════════════
EXPOSED TABLES
═══════════════════════════════════════════════════════════
Project: abc123def.supabase.co
Schema: public
Tables Found: 8
─────────────────────────────────────────────────────────
Table Inventory
─────────────────────────────────────────────────────────
1. users
├── Columns: id, email, name, avatar_url, created_at
├── Primary Key: id (uuid)
├── RLS Status: Unknown (test with supabase-audit-rls)
└── Risk: ⚠️ Contains user PII
2. profiles
├── Columns: id, user_id, bio, website, social_links
├── Primary Key: id (uuid)
├── Foreign Key: user_id → auth.users
└── Risk: ⚠️ Contains user PII
3. posts
├── Columns: id, author_id, title, content, published, created_at
├── Primary Key: id (uuid)
└── Risk: ℹ️ Content data
4. comments
├── Columns: id, post_id, user_id, content, created_at
├── Primary Key: id (uuid)
└── Risk: ℹ️ Content data
5. orders
├── Columns: id, user_id, total, status, items, created_at
├── Primary Key: id (uuid)
└── Risk: 🔴 Contains financial/transaction data
6. products
├── Columns: id, name, description, price, stock, image_url
├── Primary Key: id (uuid)
└── Risk: ℹ️ Public catalog data
7. settings
├── Columns: id, key, value, updated_at
├── Primary Key: id (uuid)
└── Risk: ⚠️ May contain sensitive configuration
8. api_keys
├── Columns: id, user_id, key_hash, name, last_used
├── Primary Key: id (uuid)
└── Risk: 🔴 Contains secrets
─────────────────────────────────────────────────────────
Summary
─────────────────────────────────────────────────────────
Total Tables: 8
High Risk: 2 (orders, api_keys)
Medium Risk: 3 (users, profiles, settings)
Low Risk: 3 (posts, comments, products)
Next Steps:
├── Run supabase-audit-tables-read to test actual data access
├── Run supabase-audit-rls to verify RLS policies
└── Review high-risk tables first
═══════════════════════════════════════════════════════════
リスク分類
テーブルは、含まれている可能性の高いデータに基づいて分類されます。
| リスク | テーブルのパターン | 例 |
|---|---|---|
| 🔴 高 | 財務、秘密情報、認証 | orders、payments、api_keys、secrets |
| ⚠️ 中 | ユーザーの個人識別情報(PII)、設定 | users、profiles、settings、preferences |
| ℹ️ 低 | 公開コンテンツ | posts、products、categories、tags |
コンテキスト出力
{
"tables": {
"count": 8,
"list": [
{
"name": "users",
"schema": "public",
"columns": ["id", "email", "name", "avatar_url", "created_at"],
"primary_key": "id",
"risk_level": "medium",
"risk_reason": "Contains user PII"
},
{
"name": "orders",
"schema": "public",
"columns": ["id", "user_id", "total", "status", "items", "created_at"],
"primary_key": "id",
"risk_level": "high",
"risk_reason": "Contains financial data"
}
],
"by_risk": {
"high": ["orders", "api_keys"],
"medium": ["users", "profiles", "settings"],
"low": ["posts", "comments", "products"]
}
}
}
非表示のテーブル
一部のテーブルは OpenAPI スキーマに表示されないことがあります。
═══════════════════════════════════════════════════════════
ADDITIONAL DISCOVERY
═══════════════════════════════════════════════════════════
Common Tables Not in Schema (testing existence):
├── _prisma_migrations: ❌ Not found
├── schema_migrations: ❌ Not found
├── audit_log: ✅ EXISTS but not in OpenAPI
└── internal_config: ❌ Not found
Note: 'audit_log' exists but may have restricted access.
Test with supabase-audit-tables-read.
═══════════════════════════════════════════════════════════
スキーマ分析
このスキルは、public 以外のスキーマも確認します。
Schema Exposure Check:
├── public: ✅ Exposed (8 tables)
├── auth: ❌ Not directly exposed (expected)
├── storage: ❌ Not directly exposed (expected)
├── extensions: ❌ Not exposed (good)
└── custom_schema: ⚠️ Exposed (3 tables) - Review if intentional
よくある問題
❌ 問題: テーブルが見つからない ✅ 解決策:
- Anon key が有効か確認する
- プロジェクト URL が正しいか確認する
- プロジェクト設定で API が無効になっている可能性があります
❌ 問題: テーブルが多すぎる ✅ 解決策: スキーマの公開範囲が過度に広い可能性があります。次の対応を検討してください。
-- Restrict exposed schemas
ALTER ROLE anon SET search_path TO public;
❌ 問題: 機密テーブルが公開されている
✅ 解決策: public スキーマから削除するか、厳格な RLS を実装してください。
テーブルの種類別の推奨事項
ユーザーテーブル
-- Ensure RLS is enabled
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- Users can only see their own data
CREATE POLICY "Users see own data" ON users
FOR SELECT USING (auth.uid() = id);
注文/決済テーブル
-- Strict RLS for financial data
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users see own orders" ON orders
FOR SELECT USING (auth.uid() = user_id);
-- No public access even for admins via API
-- Use Edge Functions for admin operations
秘密情報テーブル
-- Consider not exposing at all
REVOKE ALL ON TABLE api_keys FROM anon, authenticated;
-- Or use views that hide sensitive columns
CREATE VIEW public.api_keys_safe AS
SELECT id, name, last_used FROM api_keys;
必須:コンテキストファイルの段階的な更新
⚠️ このスキルは、実行中に追跡ファイルを段階的に更新する必要があります。最後にまとめて更新してはいけません。
重要なルール:作業を進めながら書き込む
すべての書き込みを最後にまとめて行わないでください。代わりに、次の手順を実行してください。
- アクションを開始する前に →
.sb-pentest-audit.logにアクションを記録する - テーブルを発見するたびに → 直ちに
.sb-pentest-context.jsonを更新する - 重要な手順が完了するたびに →
.sb-pentest-audit.logに完了を記録する
これにより、スキルが中断、クラッシュ、またはタイムアウトしても、その時点までの調査結果がすべて保持されます。
必須アクション(段階的に実施)
-
結果を
.sb-pentest-context.jsonに更新します。{ "tables": { "count": 8, "list": [ ... ], "by_risk": { "high": [], "medium": [], "low": [] } } } -
.sb-pentest-audit.logに記録します。[TIMESTAMP] [supabase-audit-tables-list] [START] Listing exposed tables [TIMESTAMP] [supabase-audit-tables-list] [SUCCESS] Found 8 tables [TIMESTAMP] [supabase-audit-tables-list] [CONTEXT_UPDATED] .sb-pentest-context.json updated -
ファイルが存在しない場合は、書き込む前に作成します。
コンテキストファイルを更新しないことは許容されません。
必須:証拠の収集
📁 証拠ディレクトリ: .sb-pentest-evidence/03-api-audit/tables/
作成する証拠ファイル
| ファイル | 内容 |
|---|---|
tables-list.json | 公開されているテーブルの完全な一覧 |
tables-metadata.json | テーブルごとの列の詳細と型 |
openapi-schema.json | OpenAPI/PostgREST の生スキーマ |
証拠の形式
{
"evidence_id": "API-TBL-001",
"timestamp": "2025-01-31T10:15:00Z",
"category": "api-audit",
"type": "table_enumeration",
"request": {
"method": "GET",
"url": "https://abc123def.supabase.co/rest/v1/",
"headers": {
"apikey": "[REDACTED]"
},
"curl_command": "curl -s 'https://abc123def.supabase.co/rest/v1/' -H 'apikey: $ANON_KEY'"
},
"tables_found": [
{
"name": "users",
"schema": "public",
"columns": ["id", "email", "name", "created_at"],
"primary_key": "id",
"risk_level": "high",
"risk_reason": "Contains PII"
},
{
"name": "orders",
"schema": "public",
"columns": ["id", "user_id", "total", "status"],
"primary_key": "id",
"risk_level": "high",
"risk_reason": "Financial data"
}
],
"summary": {
"total_tables": 8,
"high_risk": 2,
"medium_risk": 3,
"low_risk": 3
}
}
curl-commands.sh に追加
# === TABLE ENUMERATION ===
# List all exposed tables via OpenAPI schema
curl -s "$SUPABASE_URL/rest/v1/" -H "apikey: $ANON_KEY"
関連スキル
supabase-audit-tables-read— 実際のデータアクセスをテストしますsupabase-audit-rls— RLS ポリシーを確認しますsupabase-audit-rpc— 公開されている関数を確認します