supabase-audit-buckets-public by yoanbernabeu/supabase-pentest-skills
npx skills add https://github.com/yoanbernabeu/supabase-pentest-skills --skill supabase-audit-buckets-public🔴 关键:必须进行渐进式文件更新
你必须在处理过程中就写入上下文文件,而不仅仅是最后才写。
- 分析完每个存储桶后立即写入
.sb-pentest-context.json- 每次测试前后记录到
.sb-pentest-audit.log- 切勿等到技能完成才更新文件
- 如果技能崩溃或中断,所有之前的发现必须已经保存
这不是可选项。未能渐进式写入是关键错误。
此技能专门用于识别配置错误的公开存储桶和暴露的敏感内容。
公开存储桶允许:
| 访问类型 | 描述 |
|---|
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 直接 URL | 任何拥有 URL 的人都可以下载 |
| 枚举 | 可能可以进行文件列表 |
| 无需认证 | 不需要身份验证 |
| 缓存 | CDN 可能缓存敏感文件 |
检查配置错误的公开存储桶
深度扫描公开存储桶以查找敏感内容
═══════════════════════════════════════════════════════════
公开存储桶安全审计
═══════════════════════════════════════════════════════════
项目: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';
删除公开文件:删除或移动所有敏感文件,使其无法公开访问
轮换所有暴露的密钥:
审计访问日志:检查文件是否被未经授权的方访问
事件响应:将此视为数据泄露,并遵循你的事件响应流程
───────────────────────────────────────────────────────── 摘要 ─────────────────────────────────────────────────────────
公开存储桶: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": "立即将存储桶设为私有,轮换密钥"
}
]
}
}
修复问题后,实施以下控制措施:
-- Supabase 在 UI 中默认创建公开存储桶
-- 始终验证并在需要时更改为私有
UPDATE storage.buckets
SET public = false
WHERE name = 'new-bucket';
-- 仅允许管理员创建存储桶
REVOKE INSERT ON storage.buckets FROM authenticated;
REVOKE INSERT ON storage.buckets FROM anon;
// 上传前验证文件类型
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);
定期运行此技能:
⚠️ 此技能必须在执行过程中渐进式更新跟踪文件,而不仅仅是最后才更新。
切勿在最后批量写入所有内容。而是:
.sb-pentest-audit.log.sb-pentest-context.json这确保了如果技能被中断、崩溃或超时,所有到该点为止的发现都会被保留。
更新 .sb-pentest-context.json 并包含结果:
{
"public_bucket_audit": {
"timestamp": "...",
"public_buckets": 3,
"findings": [ ... ]
}
}
记录到 .sb-pentest-audit.log:
[时间戳] [supabase-audit-buckets-public] [开始] 审计公开存储桶
[时间戳] [supabase-audit-buckets-public] [发现] P0: backups 存储桶是公开的
[时间戳] [supabase-audit-buckets-public] [上下文已更新] .sb-pentest-context.json 已更新
如果文件不存在,在写入前创建它们。
未能更新上下文文件是不可接受的。
📁 证据目录: .sb-pentest-evidence/04-storage-audit/public-url-tests/
| 文件 | 内容 |
|---|---|
public-url-tests/[存储桶]-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": ["secrets.env 中的所有密钥"],
"incident_response": "将此视为数据泄露"
}
}
supabase-audit-buckets-list — 列出所有存储桶supabase-audit-buckets-read — 测试文件访问supabase-report — 生成综合报告每周安装次数
87
仓库
GitHub 星标
32
首次出现
2026年1月31日
安全审计
已安装于
claude-code70
codex64
opencode62
gemini-cli59
github-copilot54
cursor54
🔴 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 bucket analyzed- Log to
.sb-pentest-audit.logBEFORE and AFTER each test- 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.
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 |
Check for misconfigured public buckets
Deep scan public buckets for sensitive content
═══════════════════════════════════════════════════════════
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:
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:
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
═══════════════════════════════════════════════════════════
## Bucket 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)
- `*.sql` - Database dumps
- `*.env*` - Environment files
- `*secret*`, `*credential*` - Secrets
- `*backup*` - Backup files
- `*export*` - Data exports
### P1 - High (Usually Private)
- `*invoice*`, `*payment*` - Financial
- `*contract*`, `*agreement*` - Legal
- `*passport*`, `*id*`, `*license*` - Identity
- User-uploaded documents
### P2 - Medium (Review Needed)
- 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"
}
]
}
}
After fixing issues, implement these controls:
-- 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';
-- Only allow admin to create buckets
REVOKE INSERT ON storage.buckets FROM authenticated;
REVOKE INSERT ON storage.buckets FROM anon;
// 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);
Run this skill regularly:
⚠️ 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.jsonThis 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:
{
"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.
📁 Evidence Directory: .sb-pentest-evidence/04-storage-audit/public-url-tests/
| File | Content |
|---|---|
public-url-tests/[bucket]-access.json | Public URL access test results |
public-url-tests/sensitive-content.json | Sensitive content found |
{
"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 — List all bucketssupabase-audit-buckets-read — Test file accesssupabase-report — Generate comprehensive reportWeekly Installs
87
Repository
GitHub Stars
32
First Seen
Jan 31, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
claude-code70
codex64
opencode62
gemini-cli59
github-copilot54
cursor54
Supabase Postgres 最佳实践指南 - 8大类别性能优化规则与SQL示例
76,000 周安装