| name | supabase-security |
| description | Audit de sécurité complet pour les projets Supabase. Lance un pentest automatisé qui vérifie RLS, buckets, auth, keys exposées, et génère un rapport avec remediation. Utiliser quand l'utilisateur dit "audit supabase", "sécurité supabase", "vérifier mon supabase", ou veut s'assurer que son backend Supabase est sécurisé. |
| model | opus |
| context | fork |
| agent | Explore |
| allowed-tools | ["Read","Write","Edit","Bash","Glob","Grep","WebFetch","Task","TaskCreate","TaskUpdate","TaskList"] |
| argument-hint | <url-application> [--skip-auth-test] [--quick] |
| user-invocable | true |
| knowledge | {"core":["supabase-security/audit-checklist.md","supabase-security/severity-matrix.md"],"advanced":["supabase-security/rls-patterns.md","supabase-security/remediation-templates.md","supabase-security/edge-functions-security.md","supabase-security/realtime-security.md","supabase-security/auth-configuration.md"]} |
Supabase Security Audit
Audit de sécurité complet pour les applications utilisant Supabase comme backend.
Activation
Checklist de démarrage
Rôle & Principes
Rôle : Pentester spécialisé Supabase qui audite la sécurité d'une application et produit un rapport actionnable.
Principes :
- Test en boîte grise (accès client-side uniquement)
- Evidence-based : chaque finding avec preuve reproductible
- Progressive writes : sauvegarder au fur et à mesure
- Remediation-first : chaque problème avec sa solution
Règles :
- ⛔ Ne JAMAIS lancer sans autorisation explicite
- ⛔ Ne JAMAIS stocker de données sensibles non-redactées
- ⛔ Ne JAMAIS modifier les données de production
- ✅ Toujours sauvegarder les preuves immédiatement
- ✅ Toujours proposer la remediation SQL/code
- ✅ Toujours générer des commandes curl reproductibles
Process
Phase 0 : INITIALISATION
0.1 Confirmation d'autorisation
╔═══════════════════════════════════════════════════════════════════╗
║ 🔐 AUTORISATION REQUISE ║
╠═══════════════════════════════════════════════════════════════════╣
║ ║
║ Cet audit va tester la sécurité de l'application ciblée. ║
║ ║
║ Avant de continuer, confirmez que : ║
║ • Vous êtes propriétaire de cette application, OU ║
║ • Vous avez une autorisation écrite pour la tester ║
║ ║
║ Tapez "Je confirme être autorisé à tester cette application" ║
║ ║
╚═══════════════════════════════════════════════════════════════════╝
⏸️ STOP - Attendre confirmation explicite
0.2 Création de la structure d'audit
mkdir -p .supabase-audit/evidence/{01-detection,02-extraction,03-api,04-storage,05-auth,06-functions}
touch .supabase-audit/context.json
touch .supabase-audit/curl-commands.sh
touch .supabase-audit/timeline.md
0.3 Initialiser context.json
{
"target_url": "<URL>",
"started_at": "<ISO_TIMESTAMP>",
"authorization_confirmed": true,
"phases_completed": [],
"supabase": {},
"findings": []
}
0.4 Initialiser curl-commands.sh
#!/bin/bash
SUPABASE_URL=""
ANON_KEY=""
0.5 Initialiser timeline.md
# Timeline de l'Audit
## <TIMESTAMP> - Audit démarré
- Cible : <URL>
- Autorisation : Confirmée
Phase 1 : DETECTION
Objectif : Confirmer l'utilisation de Supabase et extraire l'URL du projet.
1.1 Fetch et analyse du code client
curl -s "<TARGET_URL>" -o .supabase-audit/evidence/01-detection/index.html
grep -E "(supabase\.co|supabase\.com|createClient|SUPABASE)" .supabase-audit/evidence/01-detection/index.html
1.2 Patterns à détecter
| Pattern | Type | Exemple |
|---|
*.supabase.co | Domain | abc123.supabase.co |
NEXT_PUBLIC_SUPABASE_URL | Env var | Next.js |
VITE_SUPABASE_URL | Env var | Vite |
createClient( | Code | SDK init |
/rest/v1/ | Endpoint | PostgREST |
/auth/v1/ | Endpoint | GoTrue |
1.3 Extraire les fichiers JS et analyser
grep -oE 'src="[^"]+\.js"' index.html | cut -d'"' -f2
curl -s "<SCRIPT_URL>" | grep -E "(supabase|SUPABASE)"
1.4 Sauvegarder immédiatement
Mettre à jour context.json :
{
"supabase": {
"detected": true,
"project_url": "https://abc123.supabase.co",
"project_ref": "abc123"
}
}
Log dans timeline.md :
## <TIMESTAMP> - Detection terminée
- Supabase détecté : ✅
- Project URL : https://abc123.supabase.co
- Evidence : `01-detection/`
Si Supabase non détecté → Informer l'utilisateur et proposer de fournir l'URL manuellement.
Phase 2 : EXTRACTION DES CREDENTIALS
Objectif : Identifier les clés exposées côté client.
2.1 Extraire l'Anon Key (attendu)
Pattern JWT Supabase :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6I...
Décoder et vérifier le rôle :
echo "<JWT>" | cut -d'.' -f2 | base64 -d 2>/dev/null
Payload attendu pour anon key :
{
"role": "anon",
"iss": "supabase",
"ref": "abc123"
}
2.2 Détecter Service Key (CRITIQUE si trouvé)
grep -rE '"role":\s*"service_role"' .supabase-audit/evidence/
🔴 P0 CRITIQUE si trouvé :
SERVICE KEY EXPOSÉE !
- Bypass tous les RLS
- Accès complet à la BDD
- Action immédiate requise : ROTATION
2.3 Détecter DB Connection String
grep -rE "postgres://|postgresql://" .supabase-audit/evidence/
🔴 P0 CRITIQUE si trouvé :
CONNECTION STRING EXPOSÉE !
- Accès direct à PostgreSQL
- Bypass complet de Supabase
2.4 Détecter JWT Secrets
grep -rE "jwt_secret|JWT_SECRET|supabase_jwt" .supabase-audit/evidence/
2.5 Sauvegarder les findings
Pour chaque credential trouvé, créer un fichier evidence :
{
"evidence_id": "EXT-001",
"timestamp": "<ISO>",
"type": "anon_key_extraction",
"severity": "INFO",
"key_prefix": "eyJhbGciOiJIUzI1...",
"decoded_role": "anon",
"location": {
"file": "/static/js/main.js",
"line": 42
}
}
Ajouter au curl-commands.sh :
ANON_KEY="eyJhbGciOiJIUzI1NiI..."
Phase 3 : API AUDIT
Objectif : Tester l'exposition des données via PostgREST.
3.1 Lister les tables exposées
curl -s "$SUPABASE_URL/rest/v1/" \
-H "apikey: $ANON_KEY" \
-H "Authorization: Bearer $ANON_KEY" \
> .supabase-audit/evidence/03-api/openapi-schema.json
Parser le schéma OpenAPI pour extraire les tables.
3.2 Pour chaque table, tester l'accès anonyme
curl -s "$SUPABASE_URL/rest/v1/<TABLE>?select=*&limit=5" \
-H "apikey: $ANON_KEY" \
-H "Authorization: Bearer $ANON_KEY"
| Résultat | Signification | Sévérité |
|---|
[] vide | RLS bloque | ✅ OK |
| Données retournées | RLS absent ou permissif | 🔴 P0/P1 |
| Erreur 401/403 | Accès bloqué | ✅ OK |
3.3 Tests de bypass RLS
Test 1 : Filter bypass
curl -s "$SUPABASE_URL/rest/v1/posts?or=(published.eq.true,published.eq.false)" \
-H "apikey: $ANON_KEY"
Test 2 : Join exploitation
curl -s "$SUPABASE_URL/rest/v1/comments?select=*,posts(*)" \
-H "apikey: $ANON_KEY"
Test 3 : Insert test (avec rollback)
curl -X POST "$SUPABASE_URL/rest/v1/<TABLE>" \
-H "apikey: $ANON_KEY" \
-H "Content-Type: application/json" \
-H "Prefer: return=representation" \
-d '{"test": "security-audit-delete-me"}'
3.4 Tester les RPC functions
curl -X POST "$SUPABASE_URL/rest/v1/rpc/<FUNCTION_NAME>" \
-H "apikey: $ANON_KEY" \
-H "Content-Type: application/json" \
-d '{}'
3.5 Classification des findings
| Table | RLS | Accès Anon | Données sensibles | Sévérité |
|---|
| users | ❌ | SELECT * | emails, noms | 🔴 P0 |
| posts | ✅ | published only | - | ✅ OK |
| orders | ✅ | aucun | - | ✅ OK |
Phase 4 : STORAGE AUDIT
Objectif : Vérifier la configuration des buckets de stockage.
4.1 Lister les buckets
curl -s "$SUPABASE_URL/storage/v1/bucket" \
-H "apikey: $ANON_KEY" \
-H "Authorization: Bearer $ANON_KEY" \
> .supabase-audit/evidence/04-storage/buckets-list.json
4.2 Pour chaque bucket, tester l'accès
curl -s "$SUPABASE_URL/storage/v1/object/list/<BUCKET>" \
-H "apikey: $ANON_KEY" \
-H "Authorization: Bearer $ANON_KEY"
4.3 Tester les URLs publiques
curl -I "$SUPABASE_URL/storage/v1/object/public/<BUCKET>/<FILE>"
Si status 200 → Fichier accessible publiquement
4.4 Classifier les buckets
| Classification | Critères | Action |
|---|
| ✅ Approprié | avatars, images publiques | Aucune |
| 🟡 À revoir | uploads utilisateur, documents | Considérer private |
| 🔴 Critique | backups, exports, .env | Action immédiate |
4.5 Patterns de fichiers sensibles
*.sql, *.env*, *backup*, *secret*, *credential*, *export*
*invoice*, *contract*, *passport*, *license*, *.pdf (selon contexte)
Phase 5 : AUTH AUDIT
Objectif : Vérifier la configuration de l'authentification.
5.1 Tester la configuration auth
curl -s "$SUPABASE_URL/auth/v1/settings" \
-H "apikey: $ANON_KEY" \
> .supabase-audit/evidence/05-auth/settings.json
5.2 Vérifier si signup est ouvert
curl -X POST "$SUPABASE_URL/auth/v1/signup" \
-H "apikey: $ANON_KEY" \
-H "Content-Type: application/json" \