supabase-audit-buckets-read
npx skills add https://github.com/yoanbernabeu/supabase-pentest-skills --skill supabase-audit-buckets-read
Agent 安装分布
Skill 文档
Bucket File Access Test
ð´ 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 tested- Log to
.sb-pentest-audit.logBEFORE and AFTER each file access 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 tests actual file access in storage buckets to verify permissions.
When to Use This Skill
- After listing buckets, to verify actual access
- To test storage RLS policy effectiveness
- To check for sensitive file exposure
- To document what files are accessible
Prerequisites
- Buckets listed (auto-invokes if needed)
- Anon key available
How It Works
The skill attempts to:
- List files in each bucket
- Read file metadata
- Download sample files (for content type verification)
- Check public URL access
Important: This is READ-ONLY. No files are modified or deleted.
Test Approach
| Bucket Type | Tests Performed |
|---|---|
| Public | Direct URL access, listing, metadata |
| Private | API listing with anon key, authenticated access |
Usage
Basic Read Test
Test read access on storage buckets
Specific Bucket
Test file access on the documents bucket
List Only (No Download)
List accessible files without downloading content
Output Format
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
BUCKET FILE ACCESS TEST
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Project: abc123def.supabase.co
Buckets Tested: 5
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
avatars (Public Bucket)
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Status: â
Expected Access
Files Found: 1,247
Sample Files:
âââ user-550e8400.jpg (45KB) - Public URL works
âââ user-6ba7b810.png (32KB) - Public URL works
âââ default.png (12KB) - Public URL works
Access Methods:
âââ Public URL: â
Accessible
âââ API Listing: â
Works
âââ Metadata: â
Visible
Assessment: Expected behavior for avatar storage.
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
documents (Private Bucket)
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Status: â
PROPERLY PROTECTED
Files Found: 0 (via anon key)
Access Methods:
âââ Public URL: â 403 Forbidden (correct)
âââ API Listing: â Empty result (RLS working)
âââ Metadata: â Not accessible (correct)
Assessment: RLS policies working correctly.
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
uploads (Public Bucket)
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Status: ð P1 - SENSITIVE FILES EXPOSED
Files Found: 3,891
Sensitive Files Detected:
âââ ð´ invoice-2025-001.pdf - Contains financial data
âââ ð´ contract-signed.pdf - Legal document
âââ ð´ id-verification.jpg - Personal ID photo!
âââ â ï¸ database-export.csv - Possible data export
âââ â ï¸ config.json - Configuration file
File Types Distribution:
âââ PDF: 1,234 (31%)
âââ Images: 2,100 (54%)
âââ Documents: 450 (12%)
âââ Other: 107 (3%)
Assessment: Bucket contains sensitive files that should not be public!
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
backups (Public - CRITICAL)
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Status: ð´ P0 - CRITICAL DATA EXPOSURE
Files Found: 45
Exposed Files:
âââ ð´ db-backup-2025-01-30.sql (125MB) - DATABASE BACKUP!
âââ ð´ db-backup-2025-01-29.sql (124MB) - DATABASE BACKUP!
âââ ð´ users-export.csv (2.3MB) - USER DATA EXPORT!
âââ ð´ secrets.env (1KB) - ENVIRONMENT SECRETS!
âââ ð´ .env.production (1KB) - PRODUCTION SECRETS!
Sample Content (secrets.env):
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxx â
â DATABASE_URL=postgresql://postgres:xxx@... â
â JWT_SECRET=super-secret-jwt-key â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â ï¸ IMMEDIATE ACTION REQUIRED:
1. Make bucket private NOW
2. Rotate ALL exposed secrets
3. Delete backup files from public access
4. Audit for unauthorized access in logs
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
temp (Private Bucket)
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Status: â
PROPERLY PROTECTED
Files Found: 0 (via anon key)
Assessment: Access correctly restricted.
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Summary
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
P0 Critical: 1 bucket (backups - DB dumps & secrets exposed)
P1 High: 1 bucket (uploads - sensitive documents in public bucket)
Protected: 2 buckets (documents, temp)
Expected: 1 bucket (avatars)
Total Files Accessible: 5,183
Sensitive Files Exposed: 52
Secret Files Exposed: 3
Immediate Actions:
1. ð´ DELETE or make private 'backups' bucket
2. ð´ Rotate Stripe key, DB password, JWT secret
3. ð Move sensitive files from 'uploads' to private bucket
4. Review all 52 sensitive files for exposure impact
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Sensitive File Detection
The skill identifies sensitive files by:
Filename Patterns
| Pattern | Risk | Type |
|---|---|---|
*.sql, backup* |
P0 | Database dumps |
.env*, *secrets* |
P0 | Secret files |
*password*, *credential* |
P0 | Credentials |
*invoice*, *payment* |
P1 | Financial |
*contract*, *agreement* |
P1 | Legal |
*id*, *passport*, *license* |
P1 | Identity |
*export*, *dump* |
P1 | Data exports |
Content Detection
For accessible files, the skill samples content for:
- API keys (patterns like
sk_live_,pk_test_) - Database credentials
- JWT secrets
- Personal information patterns
Context Output
{
"storage_access": {
"timestamp": "2025-01-31T11:30:00Z",
"buckets_tested": 5,
"findings": [
{
"bucket": "backups",
"severity": "P0",
"public": true,
"files_exposed": 45,
"sensitive_files": [
{
"path": "db-backup-2025-01-30.sql",
"size": 131072000,
"type": "database_backup",
"risk": "Full database accessible"
},
{
"path": "secrets.env",
"size": 1024,
"type": "secrets",
"exposed_secrets": ["STRIPE_SECRET_KEY", "DATABASE_URL", "JWT_SECRET"]
}
]
}
],
"summary": {
"total_files_accessible": 5183,
"sensitive_files": 52,
"secret_files": 3
}
}
}
Remediation Steps
For Exposed Secrets
# 1. Rotate Stripe keys
# Stripe Dashboard â Developers â API Keys â Roll Keys
# 2. Change database password
# Supabase Dashboard â Settings â Database â Reset Password
# 3. Regenerate JWT secret
# Supabase Dashboard â Settings â API â Regenerate JWT Secret
# 4. Update application environment variables
# Redeploy with new secrets
For Public Bucket Fix
-- Make bucket private
UPDATE storage.buckets
SET public = false
WHERE name = 'backups';
-- Delete sensitive files or move to secure location
DELETE FROM storage.objects
WHERE bucket_id = 'backups';
For Upload Bucket
-- Add RLS to restrict access
CREATE POLICY "Users access own uploads"
ON storage.objects FOR ALL
USING (
bucket_id = 'uploads'
AND auth.uid()::text = (storage.foldername(name))[1]
);
Common Issues
â Problem: Cannot list files in private bucket â Solution: This is correct behavior. RLS is working.
â Problem: Large number of files to scan â Solution: Use sampling mode for large buckets.
â Problem: File download fails â Solution: May be RLS restriction or network issue.
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 testing each bucket â Log the action to
.sb-pentest-audit.log - After each sensitive file found â Immediately update
.sb-pentest-context.json - After each bucket completed â Log the summary
This ensures that if the skill is interrupted, crashes, or times out, all findings up to that point are preserved.
Required Actions (Progressive)
-
Update
.sb-pentest-context.jsonwith results:{ "storage_access": { "timestamp": "...", "buckets_tested": 5, "findings": [ ... ], "summary": { "total_files_accessible": 5183, ... } } } -
Log to
.sb-pentest-audit.log:[TIMESTAMP] [supabase-audit-buckets-read] [START] Testing bucket file access [TIMESTAMP] [supabase-audit-buckets-read] [FINDING] P0: backups bucket has exposed secrets [TIMESTAMP] [supabase-audit-buckets-read] [CONTEXT_UPDATED] .sb-pentest-context.json updated -
If files don’t exist, create them before writing.
FAILURE TO UPDATE CONTEXT FILES IS NOT ACCEPTABLE.
MANDATORY: Evidence Collection
ð Evidence Directory: .sb-pentest-evidence/04-storage-audit/buckets/
Evidence Files to Create
| File | Content |
|---|---|
buckets/[name]/file-list.json |
Files found in bucket |
buckets/[name]/sensitive-files.json |
Sensitive files detected |
buckets/[name]/sample-contents/ |
Redacted content samples |
Evidence Format (Sensitive Files Exposed)
{
"evidence_id": "STG-READ-001",
"timestamp": "2025-01-31T10:40:00Z",
"category": "storage-audit",
"type": "file_access",
"severity": "P0",
"bucket": "backups",
"public": true,
"files_found": 45,
"sensitive_files": [
{
"path": "db-backup-2025-01-30.sql",
"size": 131072000,
"type": "database_backup",
"public_url": "https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql",
"curl_command": "curl -o backup.sql 'https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql'"
},
{
"path": "secrets.env",
"size": 1024,
"type": "secrets_file",
"content_sample": "STRIPE_SECRET_KEY=sk_live_[REDACTED]\nDATABASE_URL=postgresql://[REDACTED]",
"exposed_secrets": ["STRIPE_SECRET_KEY", "DATABASE_URL", "JWT_SECRET"]
}
],
"impact": {
"data_breach": true,
"secrets_exposed": true,
"affected_records": "All database records",
"credentials_to_rotate": ["Stripe API key", "Database password", "JWT secret"]
}
}
Add to curl-commands.sh
# === STORAGE FILE ACCESS TESTS ===
# List files in backups bucket
curl -s "$SUPABASE_URL/storage/v1/object/list/backups" \
-H "apikey: $ANON_KEY"
# Direct access to public file (P0 if accessible)
curl -I "https://abc123def.supabase.co/storage/v1/object/public/backups/secrets.env"
# Download exposed backup (for evidence - be careful with size)
# curl -o evidence-backup-sample.sql "https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql" | head -1000
Related Skills
supabase-audit-buckets-listâ List buckets firstsupabase-audit-buckets-publicâ Focus on public access issuessupabase-reportâ Generate full report