supabase-audit-buckets-public
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePublic Bucket Audit
公开存储桶审计
🔴 CRITICAL: PROGRESSIVE FILE UPDATES REQUIREDYou MUST write to context files AS YOU GO, not just at the end.
- Write to
IMMEDIATELY after each bucket analyzed.sb-pentest-context.json- Log to
BEFORE and AFTER each 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 specifically focuses on identifying misconfigured public buckets and exposed sensitive content.
🔴 严重警告:需逐步更新文件你必须逐步写入上下文文件,而不能仅在最后统一写入。
- 分析每个存储桶后立即写入
.sb-pentest-context.json- 每次测试前后都要记录到
.sb-pentest-audit.log- 切勿等到技能完成后再批量更新文件
- 若技能崩溃或中断,所有已发现的结果必须已保存
此要求为强制性规定。未逐步写入文件属于严重错误。
本技能专门用于识别配置错误的公开存储桶及暴露的敏感内容。
When to Use This Skill
适用场景
- Quick check for public bucket misconfigurations
- When you suspect sensitive data in public storage
- As a focused security check for storage
- Before deploying to production
- 快速检查公开存储桶的配置错误
- 怀疑公开存储中存在敏感数据时
- 针对存储的专项安全检查
- 生产环境部署前的检查
Prerequisites
前置条件
- Supabase URL and anon key available
- 需具备Supabase URL和匿名密钥
Why Public Buckets Are Risky
公开存储桶的风险
Public buckets allow:
| Access Type | Description |
|---|---|
| Direct URL | Anyone with the URL can download |
| Enumeration | File listing may be possible |
| No Auth | No authentication required |
| Caching | CDN may cache sensitive files |
公开存储桶允许:
| 访问类型 | 描述 |
|---|---|
| 直接URL访问 | 任何人获取URL即可下载文件 |
| 文件枚举 | 可能被遍历文件列表 |
| 无需认证 | 不需要任何身份验证 |
| 缓存风险 | CDN可能缓存敏感文件 |
Common Misconfiguration Scenarios
常见配置错误场景
- Development mistake — Bucket set public during development
- Wrong bucket — Sensitive file uploaded to public bucket
- Legacy — Bucket was public before RLS existed
- Intentional but wrong — Assumed "nobody knows the URL"
- 开发失误 — 开发阶段将存储桶设为公开
- 存储桶选错 — 敏感文件上传至公开存储桶
- 遗留问题 — RLS(行级安全)推出前存储桶已设为公开
- 主观误判 — 认为“没人知道这个URL”而设为公开
Usage
使用方法
Quick Public Bucket Check
快速公开存储桶检查
Check for misconfigured public bucketsCheck for misconfigured public bucketsDeep Scan
深度扫描
Deep scan public buckets for sensitive contentDeep scan public buckets for sensitive contentOutput Format
输出格式
═══════════════════════════════════════════════════════════
PUBLIC BUCKET SECURITY AUDIT
═══════════════════════════════════════════════════════════
Project: abc123def.supabase.co
─────────────────────────────────────────────────────────
Public Bucket Discovery
─────────────────────────────────────────────────────────
Public Buckets Found: 3/5
─────────────────────────────────────────────────────────
1. avatars ✅ APPROPRIATE
─────────────────────────────────────────────────────────
Status: Public (Expected)
Purpose: User profile pictures
Content Analysis:
├── All files are images (jpg, png, webp)
├── No sensitive filenames detected
├── File sizes appropriate for avatars (< 1MB)
└── No metadata concerns
Assessment: This bucket appropriately contains only
public user-facing content.
─────────────────────────────────────────────────────────
2. uploads 🟠 P1 - NEEDS REVIEW
─────────────────────────────────────────────────────────
Status: Public (Unexpected for this content)
Purpose: User file uploads
Content Analysis:
├── Mixed file types (PDF, DOC, images)
├── Some sensitive filenames detected
└── Should likely be private with RLS
Sensitive Content Indicators:
├── 12 files with 'invoice' in name
├── 8 files with 'contract' in name
├── 3 files with 'passport' in name
└── 156 PDF files (may contain sensitive data)
Risk Assessment:
└── 🟠 User-uploaded content publicly accessible
Anyone with filename can access any user's files
Recommendation:
```sql
-- Make bucket private
UPDATE storage.buckets
SET public = false
WHERE name = 'uploads';
-- Add user-specific RLS
CREATE POLICY "Users access own uploads"
ON storage.objects FOR ALL
USING (
bucket_id = 'uploads'
AND auth.uid()::text = (storage.foldername(name))[1]
);─────────────────────────────────────────────────────────
3. backups 🔴 P0 - CRITICAL MISCONFIGURATION
─────────────────────────────────────────────────────────
Status: Public (SHOULD NEVER BE PUBLIC)
Purpose: Database backups
⚠️ CRITICAL: Backup files publicly accessible!
Exposed Content:
├── 🔴 db-backup-2025-01-30.sql (125MB)
│ └── Full database dump with all user data
├── 🔴 db-backup-2025-01-29.sql (124MB)
│ └── Previous day backup
├── 🔴 users-export.csv (2.3MB)
│ └── User data export with emails, names
├── 🔴 secrets.env (1KB)
│ └── Contains API keys and passwords!
└── 🔴 .env.production (1KB)
└── Production environment secrets!
Public URLs (Currently Accessible):
https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql
https://abc123def.supabase.co/storage/v1/object/public/backups/secrets.env
Impact:
├── Complete database can be downloaded
├── All user PII exposed
├── All API secrets exposed
└── Full application compromise possible
═══════════════════════════════════════════════════════════
🚨 IMMEDIATE ACTION REQUIRED 🚨
═══════════════════════════════════════════════════════════
-
MAKE BUCKET PRIVATE NOW:sql
UPDATE storage.buckets SET public = false WHERE name = 'backups'; -
DELETE PUBLIC FILES: Delete or move all sensitive files from public access
-
ROTATE ALL EXPOSED SECRETS:
- Stripe API keys
- Database passwords
- JWT secrets
- Any other keys in exposed files
-
AUDIT ACCESS LOGS: Check if files were accessed by unauthorized parties
-
INCIDENT RESPONSE: Consider this a data breach and follow your incident response procedures
─────────────────────────────────────────────────────────
Summary
─────────────────────────────────────────────────────────
Public Buckets: 3
├── ✅ Appropriate: 1 (avatars)
├── 🟠 P1 Review: 1 (uploads)
└── 🔴 P0 Critical: 1 (backups)
Exposed Sensitive Files: 47
Exposed Secret Files: 2
Critical Finding: Database backups and secrets
publicly accessible via direct URL
═══════════════════════════════════════════════════════════
undefined═══════════════════════════════════════════════════════════
公开存储桶安全审计报告
═══════════════════════════════════════════════════════════
项目:abc123def.supabase.co
─────────────────────────────────────────────────────────
公开存储桶发现结果
─────────────────────────────────────────────────────────
已发现公开存储桶:3/5
─────────────────────────────────────────────────────────
1. avatars ✅ 配置合理
─────────────────────────────────────────────────────────
状态:公开(符合预期)
用途:用户头像图片
内容分析:
├── 所有文件均为图片格式(jpg, png, webp)
├── 未检测到敏感文件名
├── 文件大小符合头像要求(< 1MB)
└── 元数据无风险
评估:该存储桶仅包含面向用户的公开内容,配置合理。
─────────────────────────────────────────────────────────
2. uploads 🟠 P1 - 需要复查
─────────────────────────────────────────────────────────
状态:公开(此类型内容不应公开)
用途:用户文件上传
内容分析:
├── 文件类型混杂(PDF, DOC, 图片)
├── 检测到部分敏感文件名
└── 应通过RLS设为私有
敏感内容标识:
├── 12个文件名包含'invoice'的文件
├── 8个文件名包含'contract'的文件
└── 156个PDF文件(可能包含敏感数据)
风险评估:
└── 🟠 用户上传内容可公开访问
任何人获取文件名即可访问任意用户的文件
修复建议:
```sql
-- 将存储桶设为私有
UPDATE storage.buckets
SET public = false
WHERE name = 'uploads';
-- 添加用户专属RLS策略
CREATE POLICY "Users access own uploads"
ON storage.objects FOR ALL
USING (
bucket_id = 'uploads'
AND auth.uid()::text = (storage.foldername(name))[1]
);─────────────────────────────────────────────────────────
3. backups 🔴 P0 - 严重配置错误
─────────────────────────────────────────────────────────
状态:公开(绝对不应公开)
用途:数据库备份
⚠️ 严重警告:备份文件可公开访问!
暴露的内容:
├── 🔴 db-backup-2025-01-30.sql(125MB)
│ └── 包含所有用户数据的完整数据库备份
├── 🔴 db-backup-2025-01-29.sql(124MB)
│ └── 前一日备份文件
├── 🔴 users-export.csv(2.3MB)
│ └── 包含邮箱、姓名的用户数据导出文件
├── 🔴 secrets.env(1KB)
│ └── 包含API密钥和密码!
└── 🔴 .env.production(1KB)
└── 生产环境配置密钥!
当前可访问的公开URL:
https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql
https://abc123def.supabase.co/storage/v1/object/public/backups/secrets.env
影响:
├── 完整数据库可被下载
├── 所有用户个人可识别信息(PII)暴露
├── 所有API密钥暴露
└── 应用可能被完全攻陷
═══════════════════════════════════════════════════════════
🚨 需立即采取行动 🚨
═══════════════════════════════════════════════════════════
-
立即将存储桶设为私有:sql
UPDATE storage.buckets SET public = false WHERE name = 'backups'; -
删除公开文件: 删除或转移所有可公开访问的敏感文件
-
轮换所有暴露的密钥:
- Stripe API密钥
- 数据库密码
- JWT密钥
- 暴露文件中的其他所有密钥
-
审计访问日志: 检查是否有未授权方访问过这些文件
-
事件响应: 将此视为数据泄露事件,遵循事件响应流程
─────────────────────────────────────────────────────────
总结
─────────────────────────────────────────────────────────
公开存储桶数量:3
├── ✅ 配置合理:1个(avatars)
├── 🟠 P1需复查:1个(uploads)
└── 🔴 P0严重错误:1个(backups)
暴露的敏感文件:47个
暴露的密钥文件:2个
严重发现:数据库备份和密钥文件可通过直接URL公开访问
═══════════════════════════════════════════════════════════
undefinedBucket Classification
存储桶分类
The skill classifies buckets by content:
| Classification | Criteria | Action |
|---|---|---|
| Appropriate Public | Profile images, public assets | None needed |
| Needs Review | User uploads, mixed content | Consider making private |
| Critical Misconfiguration | Backups, secrets, exports | Immediate remediation |
本技能根据内容对存储桶进行分类:
| 分类 | 判定标准 | 处理建议 |
|---|---|---|
| 合理公开 | 头像图片、公开资源 | 无需处理 |
| 需要复查 | 用户上传内容、混合类型文件 | 考虑设为私有 |
| 严重配置错误 | 备份文件、密钥、数据导出文件 | 立即修复 |
Sensitive Content Patterns
敏感内容识别规则
P0 - Critical (Never Public)
P0 - 严重(绝对不能公开)
- - Database dumps
*.sql - - Environment files
*.env* - ,
*secret*- Secrets*credential* - - Backup files
*backup* - - Data exports
*export*
- - 数据库备份文件
*.sql - - 环境配置文件
*.env* - ,
*secret*- 密钥相关文件*credential* - - 备份文件
*backup* - - 数据导出文件
*export*
P1 - High (Usually Private)
P1 - 高风险(通常应私有)
- ,
*invoice*- Financial*payment* - ,
*contract*- Legal*agreement* - ,
*passport*,*id*- Identity*license* - User-uploaded documents
- ,
*invoice*- 财务相关文件*payment* - ,
*contract*- 法律文件*agreement* - ,
*passport*,*id*- 身份相关文件*license* - 用户上传的文档
P2 - Medium (Review Needed)
P2 - 中风险(需复查)
- Configuration files
- Log files
- Debug exports
- 配置文件
- 日志文件
- 调试导出文件
Context Output
上下文输出格式
json
{
"public_bucket_audit": {
"timestamp": "2025-01-31T12:00:00Z",
"public_buckets": 3,
"findings": [
{
"bucket": "backups",
"severity": "P0",
"issue": "Database backups and secrets publicly accessible",
"exposed_files": 45,
"critical_files": [
"db-backup-2025-01-30.sql",
"secrets.env",
".env.production"
],
"remediation": "Make bucket private immediately, rotate secrets"
}
]
}
}json
{
"public_bucket_audit": {
"timestamp": "2025-01-31T12:00:00Z",
"public_buckets": 3,
"findings": [
{
"bucket": "backups",
"severity": "P0",
"issue": "Database backups and secrets publicly accessible",
"exposed_files": 45,
"critical_files": [
"db-backup-2025-01-30.sql",
"secrets.env",
".env.production"
],
"remediation": "Make bucket private immediately, rotate secrets"
}
]
}
}Prevention Checklist
预防检查清单
After fixing issues, implement these controls:
修复问题后,需实施以下控制措施:
1. Default Private Buckets
1. 默认私有存储桶
sql
-- Supabase creates buckets public by default in UI
-- Always verify and change to private if needed
UPDATE storage.buckets
SET public = false
WHERE name = 'new-bucket';sql
-- Supabase在UI中默认创建公开存储桶
-- 需始终验证并根据需要设为私有
UPDATE storage.buckets
SET public = false
WHERE name = 'new-bucket';2. Restrict Bucket Creation
2. 限制存储桶创建权限
sql
-- Only allow admin to create buckets
REVOKE INSERT ON storage.buckets FROM authenticated;
REVOKE INSERT ON storage.buckets FROM anon;sql
-- 仅允许管理员创建存储桶
REVOKE INSERT ON storage.buckets FROM authenticated;
REVOKE INSERT ON storage.buckets FROM anon;3. File Upload Validation
3. 文件上传验证
typescript
// Validate file type before upload
const allowedTypes = ['image/jpeg', 'image/png'];
if (!allowedTypes.includes(file.type)) {
throw new Error('Invalid file type');
}
// Use user-specific paths
const path = `${user.id}/${file.name}`;
await supabase.storage.from('uploads').upload(path, file);typescript
// 上传前验证文件类型
const allowedTypes = ['image/jpeg', 'image/png'];
if (!allowedTypes.includes(file.type)) {
throw new Error('Invalid file type');
}
// 使用用户专属路径
const path = `${user.id}/${file.name}`;
await supabase.storage.from('uploads').upload(path, file);4. Regular Audits
4. 定期审计
Run this skill regularly:
- Before each production deployment
- Weekly automated scans
- After any storage configuration changes
定期运行本技能:
- 每次生产环境部署前
- 每周自动扫描
- 存储配置变更后
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 analyzing each bucket → Log the action to
.sb-pentest-audit.log - After each misconfiguration found → Immediately update
.sb-pentest-context.json - After each sensitive file detected → Log the finding immediately
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{ "public_bucket_audit": { "timestamp": "...", "public_buckets": 3, "findings": [ ... ] } } -
Log to:
.sb-pentest-audit.log[TIMESTAMP] [supabase-audit-buckets-public] [START] Auditing public buckets [TIMESTAMP] [supabase-audit-buckets-public] [FINDING] P0: backups bucket is public [TIMESTAMP] [supabase-audit-buckets-public] [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{ "public_bucket_audit": { "timestamp": "...", "public_buckets": 3, "findings": [ ... ] } } -
记录到:
.sb-pentest-audit.log[TIMESTAMP] [supabase-audit-buckets-public] [START] Auditing public buckets [TIMESTAMP] [supabase-audit-buckets-public] [FINDING] P0: backups bucket is public [TIMESTAMP] [supabase-audit-buckets-public] [CONTEXT_UPDATED] .sb-pentest-context.json updated -
若文件不存在,先创建文件再写入。
未更新上下文文件的行为是不被接受的。
MANDATORY: Evidence Collection
强制性要求:收集证据
📁 Evidence Directory:
.sb-pentest-evidence/04-storage-audit/public-url-tests/📁 证据目录:
.sb-pentest-evidence/04-storage-audit/public-url-tests/Evidence Files to Create
需创建的证据文件
| File | Content |
|---|---|
| Public URL access test results |
| Sensitive content found |
| 文件 | 内容 |
|---|---|
| 公开URL访问测试结果 |
| 发现的敏感内容 |
Evidence Format
证据格式
json
{
"evidence_id": "STG-PUB-001",
"timestamp": "2025-01-31T10:45:00Z",
"category": "storage-audit",
"type": "public_bucket_audit",
"severity": "P0",
"bucket": "backups",
"public_url_test": {
"url": "https://abc123def.supabase.co/storage/v1/object/public/backups/secrets.env",
"curl_command": "curl -I 'https://abc123def.supabase.co/storage/v1/object/public/backups/secrets.env'",
"response_status": 200,
"content_type": "text/plain",
"accessible": true
},
"assessment": {
"classification": "critical_misconfiguration",
"should_be_public": false,
"contains_sensitive_data": true,
"file_types_exposed": ["sql", "env", "csv"]
},
"remediation": {
"immediate": "UPDATE storage.buckets SET public = false WHERE name = 'backups';",
"secrets_to_rotate": ["All keys in secrets.env"],
"incident_response": "Consider this a data breach"
}
}json
{
"evidence_id": "STG-PUB-001",
"timestamp": "2025-01-31T10:45:00Z",
"category": "storage-audit",
"type": "public_bucket_audit",
"severity": "P0",
"bucket": "backups",
"public_url_test": {
"url": "https://abc123def.supabase.co/storage/v1/object/public/backups/secrets.env",
"curl_command": "curl -I 'https://abc123def.supabase.co/storage/v1/object/public/backups/secrets.env'",
"response_status": 200,
"content_type": "text/plain",
"accessible": true
},
"assessment": {
"classification": "critical_misconfiguration",
"should_be_public": false,
"contains_sensitive_data": true,
"file_types_exposed": ["sql", "env", "csv"]
},
"remediation": {
"immediate": "UPDATE storage.buckets SET public = false WHERE name = 'backups';",
"secrets_to_rotate": ["All keys in secrets.env"],
"incident_response": "Consider this a data breach"
}
}Related Skills
相关技能
- — List all buckets
supabase-audit-buckets-list - — Test file access
supabase-audit-buckets-read - — Generate comprehensive report
supabase-report
- — 列出所有存储桶
supabase-audit-buckets-list - — 测试文件访问权限
supabase-audit-buckets-read - — 生成综合报告
supabase-report