Supabase Audit Tables List

yoanbernabeu/supabase-pentest-skills/skills/audit-api/supabase-audit-tables-list

作者 yoanbernabeu0f9612276b49f241584f9d779767e35ae519875a無授權條款收錄於 2026年10月9日更新於 2026年10月9日

List all tables exposed via the Supabase PostgREST API to identify the attack surface.

僅含說明Security
AI 產生的概覽

列舉透過 PostgREST API 暴露的 Supabase 資料表,為安全稽核盤點攻擊面。

功能
使用專案 URL 與 anon key 查詢 Supabase PostgREST 的 OpenAPI schema 端點,列舉暴露的資料表、欄位、主鍵與 schema。它會依可能風險(財務、密鑰、個人隱私資料、公開內容)分類每張表,並產出清單報告以及 JSON 脈絡與證據檔案。它也會探測可能實際存在但未出現在 schema 中的常見資料表。
適用情境
適合在 Supabase 安全稽核開始時使用,在測試資料列層級安全或資料存取之前先盤點 API 攻擊面。也適合需要以結構化方式列出暴露資料表及其風險等級的團隊。
執行需求
需要 Supabase 專案 URL 與 anon key,並能透過網路存取專案的 PostgREST 端點。此技能不附帶指令碼;它會寫入脈絡、日誌與證據檔案,例如 .sb-pentest-context.json 和 .sb-pentest-evidence/03-api-audit/tables/。

List Exposed Tables

🔴 CRITICAL: PROGRESSIVE FILE UPDATES REQUIRED

You MUST write to context files AS YOU GO, not just at the end.

  • Write to .sb-pentest-context.json IMMEDIATELY after each discovery
  • Log to .sb-pentest-audit.log BEFORE and AFTER each action
  • DO NOT wait until the skill completes to update files
  • If the skill crashes or is interrupted, all prior findings must already be saved

This is not optional. Failure to write progressively is a critical error.

This skill discovers all database tables exposed through the Supabase PostgREST API.

When to Use This Skill

  • To understand the API attack surface
  • Before testing RLS policies
  • To inventory exposed data models
  • As part of a comprehensive security audit

Prerequisites

  • Supabase URL extracted (auto-invokes if needed)
  • Anon key extracted (auto-invokes if needed)

How It Works

Supabase exposes tables via PostgREST at:

https://[project-ref].supabase.co/rest/v1/

The skill uses the OpenAPI schema endpoint to enumerate tables:

https://[project-ref].supabase.co/rest/v1/?apikey=[anon-key]

What Gets Exposed

By default, Supabase exposes tables in the public schema. Tables are exposed when:

  1. They exist in an exposed schema (default: public)
  2. No explicit REVOKE has been done
  3. PostgREST can see them

Usage

Basic Table List

List tables exposed on my Supabase project

With Schema Information

List all exposed tables with column details

Output Format

═══════════════════════════════════════════════════════════ 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
═══════════════════════════════════════════════════════════

Risk Classification

Tables are classified by likely content:

RiskTable PatternsExamples
🔴 HighFinancial, secrets, authorders, payments, api_keys, secrets
⚠️ MediumUser PII, configusers, profiles, settings, preferences
ℹ️ LowPublic contentposts, products, categories, tags

Context Output

json
{  "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"]    }  }}

Hidden Tables

Some tables may not appear in the OpenAPI schema:

═══════════════════════════════════════════════════════════ 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.═══════════════════════════════════════════════════════════

Schema Analysis

The skill also checks for non-public schemas:

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

Common Issues

❌ Problem: No tables found ✅ Solution:

  • Check if anon key is valid
  • Verify project URL is correct
  • The API may be disabled in project settings

❌ Problem: Too many tables listed ✅ Solution: This may indicate overly permissive schema exposure. Consider:

sql
-- Restrict exposed schemasALTER ROLE anon SET search_path TO public;

❌ Problem: Sensitive tables exposed ✅ Solution: Either remove from public schema or implement strict RLS.

Recommendations by Table Type

User Tables

sql
-- Ensure RLS is enabledALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- Users can only see their own dataCREATE POLICY "Users see own data" ON users  FOR SELECT USING (auth.uid() = id);

Order/Payment Tables

sql
-- Strict RLS for financial dataALTER 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

Secret Tables

sql
-- Consider not exposing at allREVOKE ALL ON TABLE api_keys FROM anon, authenticated;
-- Or use views that hide sensitive columnsCREATE VIEW public.api_keys_safe AS  SELECT id, name, last_used FROM api_keys;

MANDATORY: Progressive Context File Updates

⚠️ This skill MUST update tracking files PROGRESSIVELY during execution, NOT just at the end.

Critical Rule: Write As You Go

DO NOT batch all writes at the end. Instead:

  1. Before starting any action → Log the action to .sb-pentest-audit.log
  2. After each table discovered → Immediately update .sb-pentest-context.json
  3. After each significant step → Log completion to .sb-pentest-audit.log

This ensures that if the skill is interrupted, crashes, or times out, all findings up to that point are preserved.

Required Actions (Progressive)

  1. Update .sb-pentest-context.json with results:

    json
    {  "tables": {    "count": 8,    "list": [ ... ],    "by_risk": { "high": [], "medium": [], "low": [] }  }}
  2. Log to .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
  3. If files don't exist, create them before writing.

FAILURE TO UPDATE CONTEXT FILES IS NOT ACCEPTABLE.

MANDATORY: Evidence Collection

📁 Evidence Directory: .sb-pentest-evidence/03-api-audit/tables/

Evidence Files to Create

FileContent
tables-list.jsonComplete list of exposed tables
tables-metadata.jsonColumn details and types per table
openapi-schema.jsonRaw OpenAPI/PostgREST schema

Evidence Format

json
{  "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  }}

Add to curl-commands.sh

bash
# === TABLE ENUMERATION ===# List all exposed tables via OpenAPI schemacurl -s "$SUPABASE_URL/rest/v1/" -H "apikey: $ANON_KEY"

Related Skills

  • supabase-audit-tables-read — Test actual data access
  • supabase-audit-rls — Verify RLS policies
  • supabase-audit-rpc — Check exposed functions

來源與署名

來源:yoanbernabeu/supabase-pentest-skills位於skills/audit-api/supabase-audit-tables-list提交0f96122

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架