name: supabase-audit-buckets-public description: 识别公开可访问且可能包含敏感数据的存储桶。
公开存储桶审计
🔴 关键:需要渐进式文件更新
您必须在审计过程中逐步写入上下文文件,而不是仅在结束时。
- 在分析每个存储桶后,立即写入
.sb-pentest-context.json- 在每个测试前后,记录到
.sb-pentest-audit.log- 请勿等待技能完成才更新文件
- 如果技能崩溃或被中断,所有之前的发现必须已经保存
这是强制性的。未能渐进式写入是关键错误。
该技能专注于识别配置错误的公开存储桶和暴露的敏感内容。
何时使用此技能
- 快速检查公开存储桶配置错误
- 当怀疑公开存储中包含敏感数据时
- 作为存储的专注安全检查
- 在生产环境部署前
先决条件
- Supabase URL 和匿名密钥可用
为什么公开存储桶有风险
公开存储桶允许:
| 访问类型 | 描述 |
|---|---|
| 直接 URL | 任何人拥有 URL 即可下载 |
| 枚举 | 可能列出文件 |
| 无需认证 | 无需身份验证 |
| 缓存 | CDN 可能缓存敏感文件 |
常见配置错误场景
- 开发错误 — 开发期间将存储桶设置为公开
- 错误存储桶 — 敏感文件上传到公开存储桶
- 遗留 — 在 RLS 存在前存储桶就是公开的
- 故意但错误 — 假设“没人知道 URL”
用法
快速公开存储桶检查
检查配置错误的公开存储桶
深度扫描
深度扫描公开存储桶寻找敏感内容
输出格式
═══════════════════════════════════════════════════════════
公开存储桶安全审计
═══════════════════════════════════════════════════════════
项目:abc123def.supabase.co
─────────────────────────────────────────────────────────
公开存储桶发现
─────────────────────────────────────────────────────────
发现的公开存储桶:3/5
─────────────────────────────────────────────────────────
1. avatars ✅ 适当
─────────────────────────────────────────────────────────
状态:公开(预期)
目的:用户头像图片
内容分析:
├── 所有文件为图像(jpg、png、webp)
├── 未检测到敏感文件名
├── 文件大小适合头像(< 1MB)
└── 无元数据问题
评估:此存储桶适当包含仅面向用户的公开内容。
─────────────────────────────────────────────────────────
2. uploads 🟠 P1 - 需要审查
─────────────────────────────────────────────────────────
状态:公开(对于此内容意外)
目的:用户文件上传
内容分析:
├── 混合文件类型(PDF、DOC、图像)
├── 检测到一些敏感文件名
└── 可能应设为私有并添加 RLS
敏感内容指示器:
├── 12 个文件名含“invoice”
├── 8 个文件名含“contract”
├── 3 个文件名含“passport”
└── 156 个 PDF 文件(可能包含敏感数据)
风险评估:
└── 🟠 用户上传内容公开可访问
任何人拥有文件名即可访问任何用户的文件
推荐:
```sql
-- 将存储桶设为私有
UPDATE storage.buckets
SET public = false
WHERE name = 'uploads';
-- 添加用户特定的 RLS
CREATE POLICY "用户访问自己的上传"
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 秘密暴露 └── 可能完全应用程序泄露
═══════════════════════════════════════════════════════════ 🚨 立即行动要求 🚨 ═══════════════════════════════════════════════════════════
-
立即将存储桶设为私有:
UPDATE storage.buckets SET public = false WHERE name = 'backups'; -
删除公开文件: 删除或移动所有敏感文件从公开访问
-
轮换所有暴露的秘密:
- Stripe API 密钥
- 数据库密码
- JWT 秘密
- 任何其他暴露文件中的密钥
-
审计访问日志: 检查文件是否被未授权方访问
-
事件响应: 将此视为数据泄露并遵循您的事件响应程序
───────────────────────────────────────────────────────── 摘要 ─────────────────────────────────────────────────────────
公开存储桶:3 ├── ✅ 适当:1 (avatars) ├── 🟠 P1 审查:1 (uploads) └── 🔴 P0 关键:1 (backups)
暴露的敏感文件:47 暴露的秘密文件:2
关键发现:数据库备份和秘密 通过直接 URL 公开可访问
═══════════════════════════════════════════════════════════
## 存储桶分类
该技能按内容分类存储桶:
| 分类 | 标准 | 行动 |
|----------------|----------|--------|
| **适当公开** | 头像图片、公开资产 | 无需 |
| **需要审查** | 用户上传、混合内容 | 考虑设为私有 |
| **关键配置错误** | 备份、秘密、导出 | 立即修复 |
## 敏感内容模式
### P0 - 关键(绝不应公开)
- `*.sql` - 数据库转储
- `*.env*` - 环境文件
- `*secret*`、`*credential*` - 秘密
- `*backup*` - 备份文件
- `*export*` - 数据导出
### P1 - 高(通常私有)
- `*invoice*`、`*payment*` - 财务
- `*contract*`、`*agreement*` - 法律
- `*passport*`、`*id*`、`*license*` - 身份
- 用户上传文档
### P2 - 中(需要审查)
- 配置文件
- 日志文件
- 调试导出
## 上下文输出
```json
{
"public_bucket_audit": {
"timestamp": "2025-01-31T12:00:00Z",
"public_buckets": 3,
"findings": [
{
"bucket": "backups",
"severity": "P0",
"issue": "数据库备份和秘密公开可访问",
"exposed_files": 45,
"critical_files": [
"db-backup-2025-01-30.sql",
"secrets.env",
".env.production"
],
"remediation": "立即将存储桶设为私有,轮换秘密"
}
]
}
}
预防清单
修复问题后,实施这些控制:
1. 默认私有存储桶
-- Supabase 在 UI 中默认创建公开存储桶
-- 始终验证并在需要时改为私有
UPDATE storage.buckets
SET public = false
WHERE name = 'new-bucket';
2. 限制存储桶创建
-- 仅允许管理员创建存储桶
REVOKE INSERT ON storage.buckets FROM authenticated;
REVOKE INSERT ON storage.buckets FROM anon;
3. 文件上传验证
// 上传前验证文件类型
const allowedTypes = ['image/jpeg', 'image/png'];
if (!allowedTypes.includes(file.type)) {
throw new Error('无效文件类型');
}
// 使用用户特定路径
const path = `${user.id}/${file.name}`;
await supabase.storage.from('uploads').upload(path, file);
4. 定期审计
定期运行此技能:
- 每次生产环境部署前
- 每周自动扫描
- 任何存储配置更改后
强制:渐进式上下文文件更新
⚠️ 此技能必须在执行期间逐步更新跟踪文件,而不是仅在结束时。
关键规则:逐步写入
请勿在结束时批量写入所有内容。相反:
- 在分析每个存储桶前 → 记录行动到
.sb-pentest-audit.log - 在发现每个配置错误后 → 立即更新
.sb-pentest-context.json - 在检测每个敏感文件后 → 立即记录发现
这确保如果技能被中断、崩溃或超时,所有到该点的发现都被保留。
必需行动(渐进式)
-
更新
.sb-pentest-context.json与结果:{ "public_bucket_audit": { "timestamp": "...", "public_buckets": 3, "findings": [ ... ] } } -
记录到
.sb-pentest-audit.log:[TIMESTAMP] [supabase-audit-buckets-public] [START] 审计公开存储桶 [TIMESTAMP] [supabase-audit-buckets-public] [FINDING] P0: backups 存储桶是公开的 [TIMESTAMP] [supabase-audit-buckets-public] [CONTEXT_UPDATED] .sb-pentest-context.json 已更新 -
如果文件不存在,在写入前创建。
未能更新上下文文件不可接受。
强制:证据收集
📁 证据目录: .sb-pentest-evidence/04-storage-audit/public-url-tests/
要创建的证据文件
| 文件 | 内容 |
|---|---|
public-url-tests/[bucket]-access.json |
公开 URL 访问测试结果 |
public-url-tests/sensitive-content.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"
}
}
相关技能
supabase-audit-buckets-list— 列出所有存储桶supabase-audit-buckets-read— 测试文件访问supabase-report— 生成全面报告