supabase-extract-anon-key

📁 yoanbernabeu/supabase-pentest-skills 📅 13 days ago
53
总安装量
53
周安装量
#4022
全站排名
安装命令
npx skills add https://github.com/yoanbernabeu/supabase-pentest-skills --skill supabase-extract-anon-key

Agent 安装分布

claude-code 46
codex 27
opencode 27
antigravity 21
cursor 20

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.json IMMEDIATELY after each discovery
  • Log to .sb-pentest-audit.log BEFORE 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:

  1. Anon key in client is normal — It’s designed for this
  2. RLS is critical — The anon key relies on RLS for security
  3. Never use service_role in client — Use Edge Functions instead
  4. 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:

  1. Before starting any action → Log the action to .sb-pentest-audit.log
  2. After each discovery → Immediately update .sb-pentest-context.json
  3. 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)

  1. Update .sb-pentest-context.json with extracted data:

    {
      "supabase": {
        "anon_key": "eyJhbGci...",
        "anon_key_decoded": { ... },
        "anon_key_sources": [ ... ]
      }
    }
    
  2. 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
    
  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/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 leak
  • supabase-audit-rls — Test if RLS protects your data
  • supabase-audit-tables-read — See what data is accessible with this key