Supabase公开存储桶安全审计Skill supabase-audit-buckets-public

本技能用于审计 Supabase 云存储中的公开存储桶,识别配置错误和敏感数据暴露风险,提供安全评估、修复建议和证据收集,旨在提升云存储安全性,关键词包括 Supabase、公开存储桶、安全审计、渗透测试、云安全、敏感数据保护、网络安全、DevOps 安全。

安全审计 0 次安装 0 次浏览 更新于 3/18/2026

name: supabase-audit-buckets-public description: 识别公开可访问且可能包含敏感数据的存储桶。

公开存储桶审计

🔴 关键:需要渐进式文件更新

您必须在审计过程中逐步写入上下文文件,而不是仅在结束时。

  • 在分析每个存储桶后,立即写入 .sb-pentest-context.json
  • 在每个测试前后,记录.sb-pentest-audit.log
  • 请勿等待技能完成才更新文件
  • 如果技能崩溃或被中断,所有之前的发现必须已经保存

这是强制性的。未能渐进式写入是关键错误。

该技能专注于识别配置错误的公开存储桶和暴露的敏感内容。

何时使用此技能

  • 快速检查公开存储桶配置错误
  • 当怀疑公开存储中包含敏感数据时
  • 作为存储的专注安全检查
  • 在生产环境部署前

先决条件

  • Supabase URL 和匿名密钥可用

为什么公开存储桶有风险

公开存储桶允许:

访问类型 描述
直接 URL 任何人拥有 URL 即可下载
枚举 可能列出文件
无需认证 无需身份验证
缓存 CDN 可能缓存敏感文件

常见配置错误场景

  1. 开发错误 — 开发期间将存储桶设置为公开
  2. 错误存储桶 — 敏感文件上传到公开存储桶
  3. 遗留 — 在 RLS 存在前存储桶就是公开的
  4. 故意但错误 — 假设“没人知道 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 秘密暴露 └── 可能完全应用程序泄露

═══════════════════════════════════════════════════════════ 🚨 立即行动要求 🚨 ═══════════════════════════════════════════════════════════

  1. 立即将存储桶设为私有:

    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 公开可访问

═══════════════════════════════════════════════════════════


## 存储桶分类

该技能按内容分类存储桶:

| 分类 | 标准 | 行动 |
|----------------|----------|--------|
| **适当公开** | 头像图片、公开资产 | 无需 |
| **需要审查** | 用户上传、混合内容 | 考虑设为私有 |
| **关键配置错误** | 备份、秘密、导出 | 立即修复 |

## 敏感内容模式

### 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. 定期审计

定期运行此技能:

  • 每次生产环境部署前
  • 每周自动扫描
  • 任何存储配置更改后

强制:渐进式上下文文件更新

⚠️ 此技能必须在执行期间逐步更新跟踪文件,而不是仅在结束时。

关键规则:逐步写入

请勿在结束时批量写入所有内容。相反:

  1. 在分析每个存储桶前 → 记录行动到 .sb-pentest-audit.log
  2. 在发现每个配置错误后 → 立即更新 .sb-pentest-context.json
  3. 在检测每个敏感文件后 → 立即记录发现

这确保如果技能被中断、崩溃或超时,所有到该点的发现都被保留。

必需行动(渐进式)

  1. 更新 .sb-pentest-context.json 与结果:

    {
      "public_bucket_audit": {
        "timestamp": "...",
        "public_buckets": 3,
        "findings": [ ... ]
      }
    }
    
  2. 记录到 .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 已更新
    
  3. 如果文件不存在,在写入前创建。

未能更新上下文文件不可接受。

强制:证据收集

📁 证据目录: .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 — 生成全面报告