supabase-audit-buckets-list
List all storage buckets and their configuration to identify the storage attack surface.
Works with
Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
name: supabase-audit-buckets-list
description: List all storage buckets and their configuration to identify the storage attack surface.
license: MIT
---
# List Storage Buckets
> π΄ **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 discovered**
> - Log to `.sb-pentest-audit.log` **BEFORE and AFTER each operation**
> - **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 discovers all storage buckets configured in a Supabase project.
## When to Use This Skill
- To inventory all storage buckets
- Before testing bucket access permissions
- To identify publicly accessible buckets
- As part of storage security audit
## Prerequisites
- Supabase URL and anon key available
- Detection completed
## Understanding Supabase Storage
Supabase Storage provides:
```
https://[project].supabase.co/storage/v1/
```
Buckets can be:
- **Public**: Files accessible without authentication
- **Private**: Files require authentication and RLS policies
## Storage API Endpoints
| Endpoint | Purpose |
|----------|---------|
| `/storage/v1/bucket` | List buckets |
| `/storage/v1/object/list/[bucket]` | List files in bucket |
| `/storage/v1/object/[bucket]/[path]` | Access file |
| `/storage/v1/object/public/[bucket]/[path]` | Public file URL |
## Usage
### Basic Bucket List
```
List storage buckets on my Supabase project
```
### With Configuration Details
```
List all buckets with their security settings
```
## Output Format
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
STORAGE BUCKETS
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Project: abc123def.supabase.co
Buckets Found: 5
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Bucket Inventory
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. avatars
βββ Public: β
YES
βββ File Size Limit: 1MB
βββ Allowed MIME: image/jpeg, image/png, image/webp
βββ Files (estimated): 1,247
βββ Status: βΉοΈ Expected public bucket
Public URLs pattern:
https://abc123def.supabase.co/storage/v1/object/public/avatars/[filename]
2. documents
βββ Public: β NO (Private)
βββ File Size Limit: 50MB
βββ Allowed MIME: application/pdf, application/msword, *
βββ Files (estimated): 523
βββ Status: β
Private, needs RLS verification
3. uploads
βββ Public: β
YES
βββ File Size Limit: 100MB
βββ Allowed MIME: */* (ANY)
βββ Files (estimated): 3,891
βββ Status: π P1 - Public with unrestricted MIME types
Risk: Any file type can be uploaded and accessed
Recommendation: Restrict allowed MIME types
4. backups
βββ Public: β
YES β UNEXPECTED
βββ File Size Limit: 500MB
βββ Allowed MIME: */*
βββ Files (estimated): 45
βββ Status: π΄ P0 - Sensitive bucket is PUBLIC
Risk: Backup files publicly accessible!
Immediate Action: Change to private bucket
5. temp
βββ Public: β NO
βββ File Size Limit: 10MB
βββ Allowed MIME: */*
βββ Files (estimated): 12
βββ Status: β
Private temporary storage
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Summary
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Total Buckets: 5
Public Buckets: 3
βββ Expected Public: 1 (avatars)
βββ P1 Issues: 1 (uploads - unrestricted MIME)
βββ P0 Critical: 1 (backups - should be private)
Private Buckets: 2
βββ Need RLS verification with supabase-audit-buckets-read
Next Steps:
βββ Fix 'backups' bucket - make private immediately
βββ Restrict MIME types on 'uploads' bucket
βββ Test RLS on private buckets
βββ Verify no sensitive files in public buckets
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## Bucket Configuration Analysis
| Config | Good | Bad |
|--------|------|-----|
| public: false | β
Private by default | β public: true for sensitive data |
| fileSizeLimit | β
Appropriate limits | β No limit or very large |
| allowedMimeTypes | β
Restricted list | β `*/*` allows anything |
## Context Output
```json
{
"storage": {
"buckets": [
{
"name": "avatars",
"public": true,
"file_size_limit": 1048576,
"allowed_mime_types": ["image/jpeg", "image/png", "image/webp"],
"estimated_files": 1247,
"risk_level": "info",
"expected_public": true
},
{
"name": "backups",
"public": true,
"file_size_limit": 524288000,
"allowed_mime_types": ["*/*"],
"estimated_files": 45,
"risk_level": "P0",
"finding": "Sensitive bucket publicly accessible"
}
],
"summary": {
"total": 5,
"public": 3,
"private": 2,
"p0_issues": 1,
"p1_issues": 1
}
}
}
```
## Security Recommendations
### For Public Buckets
```sql
-- Create restrictive RLS policy even for public buckets
CREATE POLICY "Public read avatars"
ON storage.objects FOR SELECT
USING (bucket_id = 'avatars');
CREATE POLICY "Users upload own avatar"
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'avatars'
AND auth.uid()::text = (storage.foldername(name))[1]
);
```
### For Private Buckets
```sql
-- Only owners can access their files
CREATE POLICY "Users access own documents"
ON storage.objects FOR ALL
USING (
bucket_id = 'documents'
AND auth.uid()::text = (storage.foldername(name))[1]
);
```
### Fix Public Backup Bucket
```sql
-- Make bucket private
UPDATE storage.buckets
SET public = false
WHERE name = 'backups';
-- Add strict RLS
CREATE POLICY "Only admins access backups"
ON storage.objects FOR ALL
USING (
bucket_id = 'backups'
AND (SELECT is_admin FROM profiles WHERE id = auth.uid())
);
```
## Common Issues
β **Problem:** Cannot list buckets
β
**Solution:** Storage API may be restricted. This is actually good security. Note as "unable to enumerate."
β **Problem:** Many buckets found
β
**Solution:** Large applications may have many. Focus on public buckets first.
β **Problem:** Bucket count doesn't match expected
β
**Solution:** Some buckets may be created dynamically. Check application code.
## 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 starting bucket enumeration** β Log the action to `.sb-pentest-audit.log`
2. **After each bucket discovered** β Immediately update `.sb-pentest-context.json`
3. **After each configuration analyzed** β Log the result
This ensures that if the skill is interrupted, crashes, or times out, all findings up to that point are preserved.
### Required Actions (Progressive)
1. **Update `.sb-pentest-context.json`** with results:
```json
{
"storage": {
"buckets": [ ... ],
"summary": { "total": 5, "public": 3, "private": 2 }
}
}
```
2. **Log to `.sb-pentest-audit.log`**:
```
[TIMESTAMP] [supabase-audit-buckets-list] [START] Listing storage buckets
[TIMESTAMP] [supabase-audit-buckets-list] [SUCCESS] Found 5 buckets
[TIMESTAMP] [supabase-audit-buckets-list] [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.**
## MANDATORY: Evidence Collection
π **Evidence Directory:** `.sb-pentest-evidence/04-storage-audit/`
### Evidence Files to Create
| File | Content |
|------|---------|
| `buckets-config.json` | All bucket configurations |
| `buckets/[name]/file-list.json` | File listing per bucket |
### Evidence Format
```json
{
"evidence_id": "STG-LIST-001",
"timestamp": "2025-01-31T10:35:00Z",
"category": "storage-audit",
"type": "bucket_enumeration",
"request": {
"method": "GET",
"url": "https://abc123def.supabase.co/storage/v1/bucket",
"curl_command": "curl -s '$URL/storage/v1/bucket' -H 'apikey: $ANON_KEY' -H 'Authorization: Bearer $ANON_KEY'"
},
"buckets": [
{
"name": "avatars",
"public": true,
"file_size_limit": 1048576,
"allowed_mime_types": ["image/jpeg", "image/png"],
"risk_level": "info",
"assessment": "Appropriate for public avatars"
},
{
"name": "backups",
"public": true,
"file_size_limit": 524288000,
"allowed_mime_types": ["*/*"],
"risk_level": "P0",
"assessment": "CRITICAL: Backup bucket should not be public"
}
],
"summary": {
"total_buckets": 5,
"public_buckets": 3,
"private_buckets": 2,
"critical_misconfigurations": 1
}
}
```
### Add to curl-commands.sh
```bash
# === STORAGE BUCKET ENUMERATION ===
# List all buckets
curl -s "$SUPABASE_URL/storage/v1/bucket" \
-H "apikey: $ANON_KEY" \
-H "Authorization: Bearer $ANON_KEY"
# List files in specific bucket
curl -s "$SUPABASE_URL/storage/v1/object/list/backups" \
-H "apikey: $ANON_KEY" \
-H "Authorization: Bearer $ANON_KEY"
```
## Related Skills
- `supabase-audit-buckets-read` β Attempt to read files
- `supabase-audit-buckets-public` β Find misconfigured public buckets
- `supabase-audit-storage-rls` β Test storage RLS policiesMore AI & ML skills
writing-shape
mattpocock/skills
Writing, exploit: shape raw material into an article, paragraph by paragraph.
275.5k
writing-fragments
mattpocock/skills
Writing, explore: mine raw fragments, no structure yet.
275.3k
full-output-enforcement
leonxlnx/taste-skill
Overrides default LLM truncation behavior. Enforces complete code generation, bans placeholder patterns, and handles token-limit splits cleanly. Apply to any task requiring exhaustive, unabridged output.
273.1k

