supabase-extract-anon-key
npx skills add https://github.com/yoanbernabeu/supabase-pentest-skills --skill supabase-extract-anon-key
Agent 安装分布
Skill 文档
Supabase Anon Key Extraction
ð´ 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 discovery- Log to
.sb-pentest-audit.logBEFORE and AFTER each action- 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 extracts the Supabase anonymous (public) API key from client-side code.
When to Use This Skill
- After extracting the Supabase URL, to get the API key for testing
- To verify that only the anon key (not service key) is exposed
- Before running API audit skills that require authentication
Prerequisites
- Supabase URL extracted (or will auto-invoke
supabase-extract-url) - Target application accessible
Understanding Anon Keys
The anon key (also called public key) is:
- â Expected to be in client-side code
- â Safe when RLS (Row Level Security) is properly configured
- â ï¸ Risky if RLS is missing or misconfigured
- â Not the same as the service_role key (which should NEVER be in client code)
Key Format
Supabase anon keys are JWTs:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFiYzEyMyIsInJvbGUiOiJhbm9uIiwiaWF0IjoxNjQwMDAwMDAwLCJleHAiOjE5NTUzNjAwMDB9.xxxx
Key characteristics:
- Starts with
eyJ(base64 encoded{"alg":) - Contains
"role":"anon"in payload - Project reference in
"ref"claim
Extraction Patterns
The skill searches for:
1. Direct Key Assignment
const SUPABASE_KEY = 'eyJhbGci...'
const SUPABASE_ANON_KEY = 'eyJhbGci...'
2. Client Initialization
createClient(url, 'eyJhbGci...')
createClient(url, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY)
3. Environment Variable Patterns
NEXT_PUBLIC_SUPABASE_ANON_KEY
VITE_SUPABASE_ANON_KEY
REACT_APP_SUPABASE_KEY
SUPABASE_KEY
Usage
Basic Extraction
Extract Supabase anon key from https://myapp.example.com
If URL Already Known
Extract anon key for project abc123def
Output Format
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
ANON KEY EXTRACTED
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Key Type: anon (public)
Severity: â¹ï¸ Expected (verify RLS configuration)
Key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJz
dXBhYmFzZSIsInJlZiI6ImFiYzEyM2RlZiIsInJvbGUiOiJhbm
9uIiwiaWF0IjoxNjQwMDAwMDAwLCJleHAiOjE5NTUzNjAwMDB9
.xxxxxxxxxxxxx
Decoded Payload:
âââ iss: supabase
âââ ref: abc123def
âââ role: anon
âââ iat: 2021-12-20T00:00:00Z
âââ exp: 2031-12-20T00:00:00Z
Found in:
âââ /static/js/main.js (line 1253)
createClient('https://abc123def.supabase.co', 'eyJhbGci...')
Next Steps:
âââ Run supabase-audit-rls to test if RLS protects your data
âââ Run supabase-audit-tables-read to see what's accessible
âââ Run supabase-extract-service-key to check for critical leaks
Context updated: .sb-pentest-context.json
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Key Validation
The skill validates the extracted key:
Validation:
âââ Format: â
Valid JWT structure
âââ Decode: â
Payload readable
âââ Role: â
Confirmed "anon" role
âââ Project: â
Matches extracted URL (abc123def)
âââ Expiry: â
Not expired (expires 2031-12-20)
Multiple Keys
If multiple keys are found:
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
MULTIPLE KEYS FOUND
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â ï¸ 2 potential Supabase keys detected
1. Anon Key (confirmed)
âââ Role: anon, Project: abc123def
2. Unknown Key
âââ Role: service_role â ï¸ SEE supabase-extract-service-key
This may be a CRITICAL security issue!
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Context Output
Saved to .sb-pentest-context.json:
{
"supabase": {
"anon_key": "eyJhbGci...",
"anon_key_decoded": {
"iss": "supabase",
"ref": "abc123def",
"role": "anon",
"iat": 1640000000,
"exp": 1955360000
},
"anon_key_sources": [
{
"file": "/static/js/main.js",
"line": 1253
}
]
}
}
Security Assessment
| Finding | Severity | Description |
|---|---|---|
| Anon key in client | â¹ï¸ Info | Expected, but test RLS |
| Anon key expired | â ï¸ P2 | Key should be rotated |
| Multiple anon keys | â ï¸ P2 | May indicate key rotation issues |
| Role is not “anon” | ð´ P0 | Wrong key type exposed! |
Common Issues
â Problem: Key found but won’t decode â Solution: May be obfuscated or split. Try:
Extract anon key with deobfuscation from https://myapp.example.com
â Problem: Key doesn’t match URL project â Solution: App may use multiple Supabase projects. Both keys are recorded.
â Problem: No key found but Supabase detected â Solution: Key may be fetched at runtime. Check network requests:
Monitor network for anon key on https://myapp.example.com
Best Practices Reminder
For developers reading this report:
- Anon key in client is normal â It’s designed for this
- RLS is critical â The anon key relies on RLS for security
- Never use service_role in client â Use Edge Functions instead
- Rotate keys periodically â Available in Supabase Dashboard
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 starting any action â Log the action to
.sb-pentest-audit.log - After each discovery â Immediately update
.sb-pentest-context.json - After each significant step â Log completion to
.sb-pentest-audit.log
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 extracted data:{ "supabase": { "anon_key": "eyJhbGci...", "anon_key_decoded": { ... }, "anon_key_sources": [ ... ] } } -
Log to
.sb-pentest-audit.log:[TIMESTAMP] [supabase-extract-anon-key] [START] Beginning anon key extraction [TIMESTAMP] [supabase-extract-anon-key] [SUCCESS] Anon key extracted [TIMESTAMP] [supabase-extract-anon-key] [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/02-extraction/
Evidence Files to Create
| File | Content |
|---|---|
extracted-anon-key.json |
Anon key with decoded JWT payload |
Evidence Format
{
"evidence_id": "EXT-ANON-001",
"timestamp": "2025-01-31T10:07:00Z",
"category": "extraction",
"type": "anon_key",
"severity": "info",
"key_data": {
"key_prefix": "eyJhbGciOiJIUzI1NiI...",
"key_suffix": "...xxxx",
"full_key_length": 256
},
"decoded_payload": {
"iss": "supabase",
"ref": "abc123def",
"role": "anon",
"iat": "2021-12-20T00:00:00Z",
"exp": "2031-12-20T00:00:00Z"
},
"source": {
"file": "/static/js/main.js",
"line": 1253,
"context": "createClient('https://abc123def.supabase.co', 'eyJhbGci...')"
},
"validation": {
"format_valid": true,
"role_confirmed": "anon",
"project_matches": true,
"expired": false
}
}
Related Skills
supabase-extract-urlâ Get URL first (auto-invoked if needed)supabase-extract-service-keyâ Check for critical service key leaksupabase-audit-rlsâ Test if RLS protects your datasupabase-audit-tables-readâ See what data is accessible with this key