supabase-audit-tables-list by yoanbernabeu/supabase-pentest-skills
npx skills add https://github.com/yoanbernabeu/supabase-pentest-skills --skill supabase-audit-tables-list🔴 关键:需要渐进式文件更新
您必须在操作过程中随时写入上下文文件,而不仅仅是在最后。
- 每次发现后立即写入
.sb-pentest-context.json- 每次操作前后记录到
.sb-pentest-audit.log- 请勿等到技能完成后再更新文件
- 如果技能崩溃或被中断,所有之前的发现必须已经保存
这不是可选项。未能渐进式写入是关键错误。
此技能用于发现通过 Supabase PostgREST API 暴露的所有数据库表。
Supabase 通过 PostgREST 在以下地址暴露数据表:
https://[project-ref].supabase.co/rest/v1/
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
该技能使用 OpenAPI 模式端点来枚举数据表:
https://[project-ref].supabase.co/rest/v1/?apikey=[anon-key]
默认情况下,Supabase 暴露 public 模式中的数据表。数据表在以下情况下会被暴露:
public)REVOKE 操作List tables exposed on my Supabase project
List all exposed tables with column details
═══════════════════════════════════════════════════════════
暴露的数据表
═══════════════════════════════════════════════════════════
项目:abc123def.supabase.co
模式:public
发现数据表:8个
─────────────────────────────────────────────────────────
数据表清单
─────────────────────────────────────────────────────────
1. users
├── 列:id, email, name, avatar_url, created_at
├── 主键:id (uuid)
├── RLS 状态:未知(使用 supabase-audit-rls 测试)
└── 风险:⚠️ 包含用户 PII
2. profiles
├── 列:id, user_id, bio, website, social_links
├── 主键:id (uuid)
├── 外键:user_id → auth.users
└── 风险:⚠️ 包含用户 PII
3. posts
├── 列:id, author_id, title, content, published, created_at
├── 主键:id (uuid)
└── 风险:ℹ️ 内容数据
4. comments
├── 列:id, post_id, user_id, content, created_at
├── 主键:id (uuid)
└── 风险:ℹ️ 内容数据
5. orders
├── 列:id, user_id, total, status, items, created_at
├── 主键:id (uuid)
└── 风险:🔴 包含财务/交易数据
6. products
├── 列:id, name, description, price, stock, image_url
├── 主键:id (uuid)
└── 风险:ℹ️ 公共目录数据
7. settings
├── 列:id, key, value, updated_at
├── 主键:id (uuid)
└── 风险:⚠️ 可能包含敏感配置
8. api_keys
├── 列:id, user_id, key_hash, name, last_used
├── 主键:id (uuid)
└── 风险:🔴 包含密钥
─────────────────────────────────────────────────────────
摘要
─────────────────────────────────────────────────────────
数据表总数:8
高风险:2 (orders, api_keys)
中风险:3 (users, profiles, settings)
低风险:3 (posts, comments, products)
后续步骤:
├── 运行 supabase-audit-tables-read 以测试实际数据访问
├── 运行 supabase-audit-rls 以验证 RLS 策略
└── 首先审查高风险数据表
═══════════════════════════════════════════════════════════
数据表根据可能的内容进行分类:
| 风险 | 数据表模式 | 示例 |
|---|---|---|
| 🔴 高 | 财务、密钥、认证 | 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 模式中:
═══════════════════════════════════════════════════════════
额外发现
═══════════════════════════════════════════════════════════
模式中未出现的常见数据表(测试存在性):
├── _prisma_migrations: ❌ 未找到
├── schema_migrations: ❌ 未找到
├── audit_log: ✅ 存在但不在 OpenAPI 中
└── internal_config: ❌ 未找到
注意:'audit_log' 存在但可能访问受限。
使用 supabase-audit-tables-read 进行测试。
═══════════════════════════════════════════════════════════
该技能还会检查非公共模式:
模式暴露检查:
├── public: ✅ 已暴露 (8个数据表)
├── auth: ❌ 未直接暴露(预期)
├── storage: ❌ 未直接暴露(预期)
├── extensions: ❌ 未暴露(良好)
└── custom_schema: ⚠️ 已暴露 (3个数据表) - 审查是否为有意为之
❌ 问题: 未找到任何数据表 ✅ 解决方案:
❌ 问题: 列出的数据表过多 ✅ 解决方案: 这可能表示模式暴露过于宽松。请考虑:
-- 限制暴露的模式
ALTER ROLE anon SET search_path TO public;
❌ 问题: 敏感数据表被暴露 ✅ 解决方案: 要么从公共模式中移除,要么实施严格的 RLS。
-- 确保启用 RLS
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- 用户只能看到自己的数据
CREATE POLICY "Users see own data" ON users
FOR SELECT USING (auth.uid() = id);
-- 对财务数据实施严格的 RLS
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users see own orders" ON orders
FOR SELECT USING (auth.uid() = user_id);
-- 即使是管理员也不允许通过 API 公开访问
-- 使用 Edge Functions 进行管理员操作
-- 考虑完全不暴露
REVOKE ALL ON TABLE api_keys FROM anon, authenticated;
-- 或者使用隐藏敏感列的视图
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
}
}
# === 数据表枚举 ===
# 通过 OpenAPI 模式列出所有暴露的数据表
curl -s "$SUPABASE_URL/rest/v1/" -H "apikey: $ANON_KEY"
supabase-audit-tables-read — 测试实际数据访问supabase-audit-rls — 验证 RLS 策略supabase-audit-rpc — 检查暴露的函数每周安装次数
93
代码仓库
GitHub 星标数
33
首次出现
2026年1月31日
安全审计
安装于
claude-code76
opencode67
codex67
gemini-cli63
github-copilot58
cursor57
🔴 CRITICAL: PROGRESSIVE FILE UPDATES REQUIRED
You MUST write to context files AS YOU GO , not just at the end.
- Write to
.sb-pentest-context.jsonIMMEDIATELY after each discovery- Log to
.sb-pentest-audit.logBEFORE 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.
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]
By default, Supabase exposes tables in the public schema. Tables are exposed when:
public)REVOKE has been doneList 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
═══════════════════════════════════════════════════════════
Tables are classified by likely content:
| Risk | Table Patterns | Examples |
|---|---|---|
| 🔴 High | Financial, secrets, auth | orders, payments, api_keys, secrets |
| ⚠️ Medium | User PII, config | users, profiles, settings, preferences |
| ℹ️ Low | Public content | 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"]
}
}
}
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.
═══════════════════════════════════════════════════════════
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
❌ Problem: No tables found ✅ Solution:
❌ Problem: Too many tables listed ✅ Solution: This may indicate overly permissive schema exposure. Consider:
-- Restrict exposed schemas
ALTER ROLE anon SET search_path TO public;
❌ Problem: Sensitive tables exposed ✅ Solution: Either remove from public schema or implement strict 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;
⚠️ This skill MUST update tracking files PROGRESSIVELY during execution, NOT just at the end.
DO NOT batch all writes at the end. Instead:
.sb-pentest-audit.log.sb-pentest-context.json.sb-pentest-audit.logThis ensures that if the skill is interrupted, crashes, or times out, all findings up to that point are preserved.
Update.sb-pentest-context.json with results:
{ "tables": { "count": 8, "list": [ ... ], "by_risk": { "high": [], "medium": [], "low": [] } } }
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
If files don't exist , create them before writing.
FAILURE TO UPDATE CONTEXT FILES IS NOT ACCEPTABLE.
📁 Evidence Directory: .sb-pentest-evidence/03-api-audit/tables/
| File | Content |
|---|---|
tables-list.json | Complete list of exposed tables |
tables-metadata.json | Column details and types per table |
openapi-schema.json | Raw OpenAPI/PostgREST schema |
{
"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
}
}
# === TABLE ENUMERATION ===
# List all exposed tables via OpenAPI schema
curl -s "$SUPABASE_URL/rest/v1/" -H "apikey: $ANON_KEY"
supabase-audit-tables-read — Test actual data accesssupabase-audit-rls — Verify RLS policiessupabase-audit-rpc — Check exposed functionsWeekly Installs
93
Repository
GitHub Stars
33
First Seen
Jan 31, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
claude-code76
opencode67
codex67
gemini-cli63
github-copilot58
cursor57
Linux云主机安全托管指南:从SSH加固到HTTPS部署
46,900 周安装