supabase-audit-buckets-public

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Public Bucket Audit

公开存储桶审计

🔴 CRITICAL: PROGRESSIVE FILE UPDATES REQUIRED
You MUST write to context files AS YOU GO, not just at the end.
  • Write to
    .sb-pentest-context.json
    IMMEDIATELY after each bucket analyzed
  • Log to
    .sb-pentest-audit.log
    BEFORE 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.
🔴 严重警告:需逐步更新文件
你必须逐步写入上下文文件,而不能仅在最后统一写入。
  • 分析每个存储桶后立即写入
    .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 TypeDescription
Direct URLAnyone with the URL can download
EnumerationFile listing may be possible
No AuthNo authentication required
CachingCDN may cache sensitive files
公开存储桶允许:
访问类型描述
直接URL访问任何人获取URL即可下载文件
文件枚举可能被遍历文件列表
无需认证不需要任何身份验证
缓存风险CDN可能缓存敏感文件

Common Misconfiguration Scenarios

常见配置错误场景

  1. Development mistake — Bucket set public during development
  2. Wrong bucket — Sensitive file uploaded to public bucket
  3. Legacy — Bucket was public before RLS existed
  4. Intentional but wrong — Assumed "nobody knows the URL"
  1. 开发失误 — 开发阶段将存储桶设为公开
  2. 存储桶选错 — 敏感文件上传至公开存储桶
  3. 遗留问题 — RLS(行级安全)推出前存储桶已设为公开
  4. 主观误判 — 认为“没人知道这个URL”而设为公开

Usage

使用方法

Quick Public Bucket Check

快速公开存储桶检查

Check for misconfigured public buckets
Check for misconfigured public buckets

Deep Scan

深度扫描

Deep scan public buckets for sensitive content
Deep scan public buckets for sensitive content

Output 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!
Impact: ├── Complete database can be downloaded ├── All user PII exposed ├── All API secrets exposed └── Full application compromise possible
═══════════════════════════════════════════════════════════ 🚨 IMMEDIATE ACTION REQUIRED 🚨 ═══════════════════════════════════════════════════════════
  1. MAKE BUCKET PRIVATE NOW:
    sql
    UPDATE storage.buckets
    SET public = false
    WHERE name = 'backups';
  2. DELETE PUBLIC FILES: Delete or move all sensitive files from public access
  3. ROTATE ALL EXPOSED SECRETS:
    • Stripe API keys
    • Database passwords
    • JWT secrets
    • Any other keys in exposed files
  4. AUDIT ACCESS LOGS: Check if files were accessed by unauthorized parties
  5. 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) └── 生产环境配置密钥!
影响: ├── 完整数据库可被下载 ├── 所有用户个人可识别信息(PII)暴露 ├── 所有API密钥暴露 └── 应用可能被完全攻陷
═══════════════════════════════════════════════════════════ 🚨 需立即采取行动 🚨 ═══════════════════════════════════════════════════════════
  1. 立即将存储桶设为私有:
    sql
    UPDATE storage.buckets
    SET public = false
    WHERE name = 'backups';
  2. 删除公开文件: 删除或转移所有可公开访问的敏感文件
  3. 轮换所有暴露的密钥:
    • Stripe API密钥
    • 数据库密码
    • JWT密钥
    • 暴露文件中的其他所有密钥
  4. 审计访问日志: 检查是否有未授权方访问过这些文件
  5. 事件响应: 将此视为数据泄露事件,遵循事件响应流程
───────────────────────────────────────────────────────── 总结 ─────────────────────────────────────────────────────────
公开存储桶数量:3 ├── ✅ 配置合理:1个(avatars) ├── 🟠 P1需复查:1个(uploads) └── 🔴 P0严重错误:1个(backups)
暴露的敏感文件:47个 暴露的密钥文件:2个
严重发现:数据库备份和密钥文件可通过直接URL公开访问
═══════════════════════════════════════════════════════════
undefined

Bucket Classification

存储桶分类

The skill classifies buckets by content:
ClassificationCriteriaAction
Appropriate PublicProfile images, public assetsNone needed
Needs ReviewUser uploads, mixed contentConsider making private
Critical MisconfigurationBackups, secrets, exportsImmediate remediation
本技能根据内容对存储桶进行分类:
分类判定标准处理建议
合理公开头像图片、公开资源无需处理
需要复查用户上传内容、混合类型文件考虑设为私有
严重配置错误备份文件、密钥、数据导出文件立即修复

Sensitive Content Patterns

敏感内容识别规则

P0 - Critical (Never Public)

P0 - 严重(绝对不能公开)

  • *.sql
    - Database dumps
  • *.env*
    - Environment files
  • *secret*
    ,
    *credential*
    - Secrets
  • *backup*
    - Backup files
  • *export*
    - Data exports
  • *.sql
    - 数据库备份文件
  • *.env*
    - 环境配置文件
  • *secret*
    ,
    *credential*
    - 密钥相关文件
  • *backup*
    - 备份文件
  • *export*
    - 数据导出文件

P1 - High (Usually Private)

P1 - 高风险(通常应私有)

  • *invoice*
    ,
    *payment*
    - Financial
  • *contract*
    ,
    *agreement*
    - Legal
  • *passport*
    ,
    *id*
    ,
    *license*
    - Identity
  • 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:
  1. Before analyzing each bucket → Log the action to
    .sb-pentest-audit.log
  2. After each misconfiguration found → Immediately update
    .sb-pentest-context.json
  3. 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.
切勿在最后批量写入。应遵循以下步骤:
  1. 分析每个存储桶前 → 将操作记录到
    .sb-pentest-audit.log
  2. 发现配置错误后 → 立即更新
    .sb-pentest-context.json
  3. 检测到敏感文件后 → 立即记录发现结果
这样可确保若技能被中断、崩溃或超时,截至该时间点的所有发现结果都已保存。

Required Actions (Progressive)

需执行的逐步操作

  1. Update
    .sb-pentest-context.json
    with results:
    json
    {
      "public_bucket_audit": {
        "timestamp": "...",
        "public_buckets": 3,
        "findings": [ ... ]
      }
    }
  2. 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
  3. If files don't exist, create them before writing.
FAILURE TO UPDATE CONTEXT FILES IS NOT ACCEPTABLE.
  1. 更新
    .sb-pentest-context.json
    以保存结果:
    json
    {
      "public_bucket_audit": {
        "timestamp": "...",
        "public_buckets": 3,
        "findings": [ ... ]
      }
    }
  2. 记录到
    .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
  3. 若文件不存在,先创建文件再写入。
未更新上下文文件的行为是不被接受的。

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

需创建的证据文件

FileContent
public-url-tests/[bucket]-access.json
Public URL access test results
public-url-tests/sensitive-content.json
Sensitive content found
文件内容
public-url-tests/[bucket]-access.json
公开URL访问测试结果
public-url-tests/sensitive-content.json
发现的敏感内容

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

相关技能

  • supabase-audit-buckets-list
    — List all buckets
  • supabase-audit-buckets-read
    — Test file access
  • supabase-report
    — Generate comprehensive report
  • supabase-audit-buckets-list
    — 列出所有存储桶
  • supabase-audit-buckets-read
    — 测试文件访问权限
  • supabase-report
    — 生成综合报告