supabase-audit-buckets-read
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBucket File Access Test
存储桶文件访问测试
🔴 CRITICAL: PROGRESSIVE FILE UPDATES REQUIREDYou MUST write to context files AS YOU GO, not just at the end.
- Write to
IMMEDIATELY after each bucket tested.sb-pentest-context.json- Log to
BEFORE and AFTER each file access test.sb-pentest-audit.log- 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 tests actual file access in storage buckets to verify permissions.
🔴 严重警告:需逐步更新文件你必须逐步写入上下文文件,而不是仅在最后统一写入。
- 测试完每个存储桶后,立即写入
.sb-pentest-context.json- 在每次文件访问测试前后,都要记录到
.sb-pentest-audit.log- 禁止等到技能完成后再批量更新文件
- 如果技能崩溃或被中断,所有已发现的结果必须已保存
此要求为强制性规定,未逐步写入文件属于严重错误。
本技能通过测试存储桶的实际文件访问权限,来验证权限设置是否合规。
When to Use This Skill
适用场景
- After listing buckets, to verify actual access
- To test storage RLS policy effectiveness
- To check for sensitive file exposure
- To document what files are accessible
- 列出存储桶后,验证实际访问权限
- 测试存储RLS策略的有效性
- 检查敏感文件是否暴露
- 记录可访问的文件清单
Prerequisites
前置条件
- Buckets listed (auto-invokes if needed)
- Anon key available
- 已列出存储桶(若未完成,将自动调用对应技能)
- 拥有匿名密钥(anon key)
How It Works
工作原理
The skill attempts to:
- List files in each bucket
- Read file metadata
- Download sample files (for content type verification)
- Check public URL access
Important: This is READ-ONLY. No files are modified or deleted.
本技能会尝试执行以下操作:
- 列出每个存储桶中的文件
- 读取文件元数据
- 下载样本文件(用于验证内容类型)
- 检查公开URL的可访问性
重要提示: 本技能仅执行只读操作,不会修改或删除任何文件。
Test Approach
测试方案
| Bucket Type | Tests Performed |
|---|---|
| Public | Direct URL access, listing, metadata |
| Private | API listing with anon key, authenticated access |
| 存储桶类型 | 执行的测试内容 |
|---|---|
| 公开存储桶 | 直接URL访问、文件列出、元数据读取 |
| 私有存储桶 | 使用匿名密钥的API列出、已认证访问测试 |
Usage
使用方法
Basic Read Test
基础读取测试
Test read access on storage bucketsTest read access on storage bucketsSpecific Bucket
指定存储桶测试
Test file access on the documents bucketTest file access on the documents bucketList Only (No Download)
仅列出文件(不下载)
List accessible files without downloading contentList accessible files without downloading contentOutput Format
输出格式
═══════════════════════════════════════════════════════════
BUCKET FILE ACCESS TEST
═══════════════════════════════════════════════════════════
Project: abc123def.supabase.co
Buckets Tested: 5
─────────────────────────────────────────────────────────
avatars (Public Bucket)
─────────────────────────────────────────────────────────
Status: ✅ Expected Access
Files Found: 1,247
Sample Files:
├── user-550e8400.jpg (45KB) - Public URL works
├── user-6ba7b810.png (32KB) - Public URL works
└── default.png (12KB) - Public URL works
Access Methods:
├── Public URL: ✅ Accessible
├── API Listing: ✅ Works
└── Metadata: ✅ Visible
Assessment: Expected behavior for avatar storage.
─────────────────────────────────────────────────────────
documents (Private Bucket)
─────────────────────────────────────────────────────────
Status: ✅ PROPERLY PROTECTED
Files Found: 0 (via anon key)
Access Methods:
├── Public URL: ❌ 403 Forbidden (correct)
├── API Listing: ❌ Empty result (RLS working)
└── Metadata: ❌ Not accessible (correct)
Assessment: RLS policies working correctly.
─────────────────────────────────────────────────────────
uploads (Public Bucket)
─────────────────────────────────────────────────────────
Status: 🟠 P1 - SENSITIVE FILES EXPOSED
Files Found: 3,891
Sensitive Files Detected:
├── 🔴 invoice-2025-001.pdf - Contains financial data
├── 🔴 contract-signed.pdf - Legal document
├── 🔴 id-verification.jpg - Personal ID photo!
├── ⚠️ database-export.csv - Possible data export
└── ⚠️ config.json - Configuration file
File Types Distribution:
├── PDF: 1,234 (31%)
├── Images: 2,100 (54%)
├── Documents: 450 (12%)
└── Other: 107 (3%)
Assessment: Bucket contains sensitive files that should not be public!
─────────────────────────────────────────────────────────
backups (Public - CRITICAL)
─────────────────────────────────────────────────────────
Status: 🔴 P0 - CRITICAL DATA EXPOSURE
Files Found: 45
Exposed Files:
├── 🔴 db-backup-2025-01-30.sql (125MB) - DATABASE BACKUP!
├── 🔴 db-backup-2025-01-29.sql (124MB) - DATABASE BACKUP!
├── 🔴 users-export.csv (2.3MB) - USER DATA EXPORT!
├── 🔴 secrets.env (1KB) - ENVIRONMENT SECRETS!
└── 🔴 .env.production (1KB) - PRODUCTION SECRETS!
Sample Content (secrets.env):
┌─────────────────────────────────────────────────────────┐
│ STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxx │
│ DATABASE_URL=postgresql://postgres:xxx@... │
│ JWT_SECRET=super-secret-jwt-key │
└─────────────────────────────────────────────────────────┘
⚠️ IMMEDIATE ACTION REQUIRED:
1. Make bucket private NOW
2. Rotate ALL exposed secrets
3. Delete backup files from public access
4. Audit for unauthorized access in logs
─────────────────────────────────────────────────────────
temp (Private Bucket)
─────────────────────────────────────────────────────────
Status: ✅ PROPERLY PROTECTED
Files Found: 0 (via anon key)
Assessment: Access correctly restricted.
─────────────────────────────────────────────────────────
Summary
─────────────────────────────────────────────────────────
P0 Critical: 1 bucket (backups - DB dumps & secrets exposed)
P1 High: 1 bucket (uploads - sensitive documents in public bucket)
Protected: 2 buckets (documents, temp)
Expected: 1 bucket (avatars)
Total Files Accessible: 5,183
Sensitive Files Exposed: 52
Secret Files Exposed: 3
Immediate Actions:
1. 🔴 DELETE or make private 'backups' bucket
2. 🔴 Rotate Stripe key, DB password, JWT secret
3. 🟠 Move sensitive files from 'uploads' to private bucket
4. Review all 52 sensitive files for exposure impact
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
存储桶文件访问测试
═══════════════════════════════════════════════════════════
项目:abc123def.supabase.co
已测试存储桶数量:5
─────────────────────────────────────────────────────────
avatars(公开存储桶)
─────────────────────────────────────────────────────────
状态:✅ 符合预期访问权限
发现文件数量:1,247
样本文件:
├── user-550e8400.jpg(45KB)- 公开URL可正常访问
├── user-6ba7b810.png(32KB)- 公开URL可正常访问
└── default.png(12KB)- 公开URL可正常访问
访问方式验证:
├── 公开URL:✅ 可访问
├── API列出:✅ 正常工作
└── 元数据:✅ 可见
评估:符合头像存储的预期行为。
─────────────────────────────────────────────────────────
documents(私有存储桶)
─────────────────────────────────────────────────────────
状态:✅ 已正确保护
发现文件数量:0(通过匿名密钥)
访问方式验证:
├── 公开URL:❌ 403 禁止访问(符合预期)
├── API列出:❌ 无返回结果(RLS策略生效)
└── 元数据:❌ 不可访问(符合预期)
评估:RLS策略正常工作。
─────────────────────────────────────────────────────────
uploads(公开存储桶)
─────────────────────────────────────────────────────────
状态:🟠 P1 - 敏感文件暴露
发现文件数量:3,891
检测到的敏感文件:
├── 🔴 invoice-2025-001.pdf - 包含财务数据
├── 🔴 contract-signed.pdf - 法律文档
├── 🔴 id-verification.jpg - 个人身份证件照片!
├── ⚠️ database-export.csv - 可能为数据导出文件
└── ⚠️ config.json - 配置文件
文件类型分布:
├── PDF:1,234(31%)
├── 图片:2,100(54%)
├── 文档:450(12%)
└── 其他:107(3%)
评估:该存储桶包含不应公开的敏感文件!
─────────────────────────────────────────────────────────
backups(公开存储桶 - 严重风险)
─────────────────────────────────────────────────────────
状态:🔴 P0 - 关键数据暴露
发现文件数量:45
暴露的文件:
├── 🔴 db-backup-2025-01-30.sql(125MB)- 数据库备份文件!
├── 🔴 db-backup-2025-01-29.sql(124MB)- 数据库备份文件!
├── 🔴 users-export.csv(2.3MB)- 用户数据导出文件!
├── 🔴 secrets.env(1KB)- 环境密钥文件!
└── 🔴 .env.production(1KB)- 生产环境密钥文件!
样本内容(secrets.env):
┌─────────────────────────────────────────────────────────┐
│ STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxx │
│ DATABASE_URL=postgresql://postgres:xxx@... │
│ JWT_SECRET=super-secret-jwt-key │
└─────────────────────────────────────────────────────────┘
⚠️ 需立即采取行动:
1. 立即将该存储桶设为私有
2. 轮换所有已暴露的密钥
3. 删除公开可访问的备份文件
4. 审计日志中是否存在未授权访问记录
─────────────────────────────────────────────────────────
temp(私有存储桶)
─────────────────────────────────────────────────────────
状态:✅ 已正确保护
发现文件数量:0(通过匿名密钥)
评估:访问权限已正确限制。
─────────────────────────────────────────────────────────
总结
─────────────────────────────────────────────────────────
P0 关键风险:1个存储桶(backups - 数据库备份和密钥暴露)
P1 高风险:1个存储桶(uploads - 敏感文档存于公开存储桶)
已正确保护:2个存储桶(documents、temp)
符合预期:1个存储桶(avatars)
可访问文件总数:5,183
暴露的敏感文件数量:52
暴露的密钥文件数量:3
立即执行的操作:
1. 🔴 删除或设为私有 'backups' 存储桶
2. 🔴 轮换Stripe密钥、数据库密码、JWT密钥
3. 🟠 将uploads中的敏感文件移至私有存储桶
4. 评估所有52个敏感文件的暴露影响
═══════════════════════════════════════════════════════════Sensitive File Detection
敏感文件检测
The skill identifies sensitive files by:
本技能通过以下方式识别敏感文件:
Filename Patterns
文件名模式
| Pattern | Risk | Type |
|---|---|---|
| P0 | Database dumps |
| P0 | Secret files |
| P0 | Credentials |
| P1 | Financial |
| P1 | Legal |
| P1 | Identity |
| P1 | Data exports |
| 模式 | 风险等级 | 类型 |
|---|---|---|
| P0 | 数据库备份 |
| P0 | 密钥文件 |
| P0 | 凭证文件 |
| P1 | 财务文件 |
| P1 | 法律文件 |
| P1 | 身份证件 |
| P1 | 数据导出文件 |
Content Detection
内容检测
For accessible files, the skill samples content for:
- API keys (patterns like ,
sk_live_)pk_test_ - Database credentials
- JWT secrets
- Personal information patterns
对于可访问的文件,本技能会抽样检测以下内容:
- API密钥(如 、
sk_live_等模式)pk_test_ - 数据库凭证
- JWT密钥
- 个人信息模式
Context Output
上下文输出
json
{
"storage_access": {
"timestamp": "2025-01-31T11:30:00Z",
"buckets_tested": 5,
"findings": [
{
"bucket": "backups",
"severity": "P0",
"public": true,
"files_exposed": 45,
"sensitive_files": [
{
"path": "db-backup-2025-01-30.sql",
"size": 131072000,
"type": "database_backup",
"risk": "Full database accessible"
},
{
"path": "secrets.env",
"size": 1024,
"type": "secrets",
"exposed_secrets": ["STRIPE_SECRET_KEY", "DATABASE_URL", "JWT_SECRET"]
}
]
}
],
"summary": {
"total_files_accessible": 5183,
"sensitive_files": 52,
"secret_files": 3
}
}
}json
{
"storage_access": {
"timestamp": "2025-01-31T11:30:00Z",
"buckets_tested": 5,
"findings": [
{
"bucket": "backups",
"severity": "P0",
"public": true,
"files_exposed": 45,
"sensitive_files": [
{
"path": "db-backup-2025-01-30.sql",
"size": 131072000,
"type": "database_backup",
"risk": "Full database accessible"
},
{
"path": "secrets.env",
"size": 1024,
"type": "secrets",
"exposed_secrets": ["STRIPE_SECRET_KEY", "DATABASE_URL", "JWT_SECRET"]
}
]
}
],
"summary": {
"total_files_accessible": 5183,
"sensitive_files": 52,
"secret_files": 3
}
}
}Remediation Steps
修复步骤
For Exposed Secrets
针对暴露的密钥
bash
undefinedbash
undefined1. Rotate Stripe keys
1. 轮换Stripe密钥
Stripe Dashboard → Developers → API Keys → Roll Keys
Stripe Dashboard → Developers → API Keys → Roll Keys
2. Change database password
2. 修改数据库密码
Supabase Dashboard → Settings → Database → Reset Password
Supabase Dashboard → Settings → Database → Reset Password
3. Regenerate JWT secret
3. 重新生成JWT密钥
Supabase Dashboard → Settings → API → Regenerate JWT Secret
Supabase Dashboard → Settings → API → Regenerate JWT Secret
4. Update application environment variables
4. 更新应用程序环境变量
Redeploy with new secrets
使用新密钥重新部署
undefinedundefinedFor Public Bucket Fix
针对公开存储桶的修复
sql
-- Make bucket private
UPDATE storage.buckets
SET public = false
WHERE name = 'backups';
-- Delete sensitive files or move to secure location
DELETE FROM storage.objects
WHERE bucket_id = 'backups';sql
-- 将存储桶设为私有
UPDATE storage.buckets
SET public = false
WHERE name = 'backups';
-- 删除敏感文件或移至安全位置
DELETE FROM storage.objects
WHERE bucket_id = 'backups';For Upload Bucket
针对上传存储桶的修复
sql
-- Add RLS to restrict access
CREATE POLICY "Users access own uploads"
ON storage.objects FOR ALL
USING (
bucket_id = 'uploads'
AND auth.uid()::text = (storage.foldername(name))[1]
);sql
-- 添加RLS策略限制访问
CREATE POLICY "Users access own uploads"
ON storage.objects FOR ALL
USING (
bucket_id = 'uploads'
AND auth.uid()::text = (storage.foldername(name))[1]
);Common Issues
常见问题
❌ Problem: Cannot list files in private bucket
✅ Solution: This is correct behavior. RLS is working.
❌ Problem: Large number of files to scan
✅ Solution: Use sampling mode for large buckets.
❌ Problem: File download fails
✅ Solution: May be RLS restriction or network issue.
❌ 问题:无法列出私有存储桶中的文件
✅ 解决方案:这是正确行为,RLS策略已生效。
❌ 问题:需要扫描的文件数量过多
✅ 解决方案:对大型存储桶使用抽样模式。
❌ 问题:文件下载失败
✅ 解决方案:可能是RLS限制或网络问题导致。
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:
- Before testing each bucket → Log the action to
.sb-pentest-audit.log - After each sensitive file found → Immediately update
.sb-pentest-context.json - After each bucket completed → Log the summary
This ensures that if the skill is interrupted, crashes, or times out, all findings up to that point are preserved.
禁止在最后批量写入。应执行以下操作:
- 测试每个存储桶前 → 将操作记录到
.sb-pentest-audit.log - 发现每个敏感文件后 → 立即更新
.sb-pentest-context.json - 每个存储桶测试完成后 → 记录总结信息
这样可确保如果技能被中断、崩溃或超时,所有已完成的测试结果都已保存。
Required Actions (Progressive)
必须执行的逐步操作
-
Updatewith results:
.sb-pentest-context.jsonjson{ "storage_access": { "timestamp": "...", "buckets_tested": 5, "findings": [ ... ], "summary": { "total_files_accessible": 5183, ... } } } -
Log to:
.sb-pentest-audit.log[TIMESTAMP] [supabase-audit-buckets-read] [START] Testing bucket file access [TIMESTAMP] [supabase-audit-buckets-read] [FINDING] P0: backups bucket has exposed secrets [TIMESTAMP] [supabase-audit-buckets-read] [CONTEXT_UPDATED] .sb-pentest-context.json updated -
If files don't exist, create them before writing.
FAILURE TO UPDATE CONTEXT FILES IS NOT ACCEPTABLE.
-
更新以保存结果:
.sb-pentest-context.jsonjson{ "storage_access": { "timestamp": "...", "buckets_tested": 5, "findings": [ ... ], "summary": { "total_files_accessible": 5183, ... } } } -
记录到:
.sb-pentest-audit.log[TIMESTAMP] [supabase-audit-buckets-read] [START] Testing bucket file access [TIMESTAMP] [supabase-audit-buckets-read] [FINDING] P0: backups bucket has exposed secrets [TIMESTAMP] [supabase-audit-buckets-read] [CONTEXT_UPDATED] .sb-pentest-context.json updated -
若文件不存在,在写入前先创建。
未更新上下文文件属于违规行为。
MANDATORY: Evidence Collection
强制性要求:证据收集
📁 Evidence Directory:
.sb-pentest-evidence/04-storage-audit/buckets/📁 证据目录:
.sb-pentest-evidence/04-storage-audit/buckets/Evidence Files to Create
需要创建的证据文件
| File | Content |
|---|---|
| Files found in bucket |
| Sensitive files detected |
| Redacted content samples |
| 文件 | 内容 |
|---|---|
| 存储桶中发现的文件列表 |
| 检测到的敏感文件列表 |
| 已脱敏的内容样本 |
Evidence Format (Sensitive Files Exposed)
证据格式(敏感文件暴露)
json
{
"evidence_id": "STG-READ-001",
"timestamp": "2025-01-31T10:40:00Z",
"category": "storage-audit",
"type": "file_access",
"severity": "P0",
"bucket": "backups",
"public": true,
"files_found": 45,
"sensitive_files": [
{
"path": "db-backup-2025-01-30.sql",
"size": 131072000,
"type": "database_backup",
"public_url": "https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql",
"curl_command": "curl -o backup.sql 'https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql'"
},
{
"path": "secrets.env",
"size": 1024,
"type": "secrets_file",
"content_sample": "STRIPE_SECRET_KEY=sk_live_[REDACTED]\nDATABASE_URL=postgresql://[REDACTED]",
"exposed_secrets": ["STRIPE_SECRET_KEY", "DATABASE_URL", "JWT_SECRET"]
}
],
"impact": {
"data_breach": true,
"secrets_exposed": true,
"affected_records": "All database records",
"credentials_to_rotate": ["Stripe API key", "Database password", "JWT secret"]
}
}json
{
"evidence_id": "STG-READ-001",
"timestamp": "2025-01-31T10:40:00Z",
"category": "storage-audit",
"type": "file_access",
"severity": "P0",
"bucket": "backups",
"public": true,
"files_found": 45,
"sensitive_files": [
{
"path": "db-backup-2025-01-30.sql",
"size": 131072000,
"type": "database_backup",
"public_url": "https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql",
"curl_command": "curl -o backup.sql 'https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql'"
},
{
"path": "secrets.env",
"size": 1024,
"type": "secrets_file",
"content_sample": "STRIPE_SECRET_KEY=sk_live_[REDACTED]\nDATABASE_URL=postgresql://[REDACTED]",
"exposed_secrets": ["STRIPE_SECRET_KEY", "DATABASE_URL", "JWT_SECRET"]
}
],
"impact": {
"data_breach": true,
"secrets_exposed": true,
"affected_records": "All database records",
"credentials_to_rotate": ["Stripe API key", "Database password", "JWT secret"]
}
}Add to curl-commands.sh
添加到 curl-commands.sh
bash
undefinedbash
undefined=== STORAGE FILE ACCESS TESTS ===
=== STORAGE FILE ACCESS TESTS ===
List files in backups bucket
List files in backups bucket
curl -s "$SUPABASE_URL/storage/v1/object/list/backups"
-H "apikey: $ANON_KEY"
-H "apikey: $ANON_KEY"
curl -s "$SUPABASE_URL/storage/v1/object/list/backups"
-H "apikey: $ANON_KEY"
-H "apikey: $ANON_KEY"
Direct access to public file (P0 if accessible)
Direct access to public file (P0 if accessible)
Download exposed backup (for evidence - be careful with size)
Download exposed backup (for evidence - be careful with size)
curl -o evidence-backup-sample.sql "https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql" | head -1000
curl -o evidence-backup-sample.sql "https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql" | head -1000
undefinedundefinedRelated Skills
相关技能
- — List buckets first
supabase-audit-buckets-list - — Focus on public access issues
supabase-audit-buckets-public - — Generate full report
supabase-report
- — 先列出存储桶
supabase-audit-buckets-list - — 专注于公开访问问题
supabase-audit-buckets-public - — 生成完整报告
supabase-report