К основному содержанию
скилл CX Codex

supabase-audit-authenticated — скилл для Claude Code: аудит доступа

Создаёт тестового пользователя в Supabase и сравнивает, что видит авторизованный юзер, а что аноним. Ловит IDOR, доступ к чужим данным и эскалацию привилегий.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add yoanbernabeu/supabase-pentest-skills --skill supabase-audit-authenticated -a claude-code
Открыть на GitHub

Что делает supabase-audit-authenticated

Скилл заводит в вашем проекте Supabase тестового пользователя с почтой вида pentest-[random]@security-audit.local и случайным паролем от 32 символов. Дальше он логинится под ним, получает JWT и прогоняет таблицы, хранилище и Realtime: сколько строк отдаётся анонимно, сколько — авторизованному, видит ли тестовый юзер только свои записи или чужие тоже.

Отдельный блок — IDOR. Скилл пробует запросить данные по чужому user_id и по условию «всё, кроме моего», и если запрос возвращает строки, это уже находка. Результаты он пишет в .sb-pentest-context.json и .sb-pentest-audit.log по ходу проверки, а не в конце, чтобы ничего не потерялось при обрыве.

Перед запуском нужно ваше явное согласие: скилл спрашивает подтверждение и без ответа «yes, create test user» не работает. Ещё понадобится открытая регистрация (или invite-поток) и anon key. В конце он предложит удалить тестового пользователя. Если signup в проекте закрыт, проверка не стартует — это повод сначала открыть invite-флоу.

Какие задачи решает

  • сравнить, сколько строк отдаёт таблица анониму и авторизованному
  • найти IDOR при запросе данных по чужому user_id
  • проверить, не утекают ли чужие профили через фильтр «всё, кроме моего»
  • убедиться, что RLS пускает авторизованного юзера только к своим записям
  • проверить доступ к файлам в Storage и подписки Realtime под тестовым аккаунтом

Примеры запросов агенту

  • создай тестового пользователя и сравни доступ авторизованного с анонимным
  • прогони аудит на IDOR по таблице orders
  • проверь, видит ли тестовый юзер чужие профили в profiles

Как установить supabase-audit-authenticated

1Через Skills CLI (Vercel)

npx skills add yoanbernabeu/supabase-pentest-skills --skill supabase-audit-authenticated -a claude-code

2Вручную: положить файлы

~/.claude/skills/supabase-audit-authenticated/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/supabase-audit-authenticated/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора11

supabase-audit-rpc Перечисляет открытые PostgreSQL-функции в RPC-эндпоинте Supabase и проверяет их на обход RLS и SQL-инъекции. CX Codex +1 524установок supabase-audit-realtime Проверяет WebSocket-каналы Supabase Realtime на подписки без авторизации и утечку данных. Нужен, если Realtime отдаёт что-то чувствительное. CX Codex +1 522установок supabase-help Показывает все 24 скилла аудита безопасности Supabase с командами и примерами. Пригодится, когда нужно вспомнить, какой скилл за что отвечает. CX Codex +1 503установок supabase-audit-tables-read Читает данные из открытых таблиц Supabase, чтобы показать, что реально утекает наружу. Пригодится, когда нужно проверить политики RLS до релиза. CX Codex +1 487установок supabase-audit-auth-users Проверяет, можно ли по ответам Supabase Auth понять, зарегистрирован ли email. Пригодится перед выкладкой в прод. CX Codex +1 484установок supabase-audit-buckets-list Перечисляет все storage-бакеты проекта Supabase вместе с настройками и помечает публичные как риск. Пригодится перед проверкой прав доступа к файлам. CX Codex +1 474установок supabase-audit-buckets-read Скилл перебирает файлы в бакетах Supabase Storage и показывает, что реально доступно по anon-ключу. Пригодится, когда нужно проверить политики RLS до релиза. CX Codex +1 471установок supabase-audit-auth-signup Проверяет, открыта ли регистрация в вашем проекте Supabase, и ищет векторы злоупотребления: спам-аккаунты, слабые пароли, одноразовые почты. CX Codex +1 473установок

Похожие

supabase-security-audit davila7 Слэш-команда прогоняет аудит безопасности проекта на Supabase: проверяет RLS-политики, права ролей, ключи API и настройки аутентификации. 1 020установок supabase-postgres-best-practices официальный supabase Скилл содержит правила оптимизации Postgres от команды Supabase. Помогает писать SQL-запросы, проектировать схемы и настраивать RLS. CX Codex GP ChatGPT 40установок supabase официальный supabase Скилл помогает настраивать базу данных, аутентификацию и RLS в Supabase без скрытых дыр в безопасности. CX Codex GP ChatGPT 8установок supabase-development Mindrally Задаёт агенту порядок работы с Supabase: схема базы, RLS-политики, авторизация, realtime-подписки и Edge Functions. CX Codex +1 699установок supabase-schema-architect davila7 Субагент проектирует схемы PostgreSQL в Supabase, планирует миграции и пишет политики RLS. Пригодится, когда база растёт и надо навести порядок в доступе. 3 839установок nextjs15-supabase-cursorrules-prompt-file PatrickJS Правило для Cursor, которое держит агента в рамках стека Next.js 15, Supabase и TypeScript strict — от проверки сессии до RLS и ключей Stripe. ★ 41 011звёзд репо

Рядом в теме «Безопасность»

Всё по теме «Безопасность» →

Вопросы о supabase-audit-authenticated

Как установить supabase-audit-authenticated в Claude?

Выполните npx skills add yoanbernabeu/supabase-pentest-skills --skill supabase-audit-authenticated -a claude-code. После этого файл скилла лежит в ~/.claude/skills/supabase-audit-authenticated/SKILL.md.

Что делает supabase-audit-authenticated?

Создаёт тестового пользователя в Supabase и сравнивает, что доступно авторизованному, а что анониму. Ищет IDOR, доступ к чужим данным и эскалацию привилегий.

Что нужно перед запуском скилла?

Явное согласие на создание тестового пользователя, открытая регистрация или invite-поток и anon key. Анонимный аудит советуют пройти заранее.

Исходный текст

SKILL.md · MIT
---
name: supabase-audit-authenticated
description: Create a test user (with explicit permission) to audit what authenticated users can access vs anonymous users. Detects IDOR, cross-user access, and privilege escalation.
---

# Authenticated User Audit

> 🔴 **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 test**
> - 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 creates a test user (with explicit permission) to compare authenticated vs anonymous access and detect IDOR vulnerabilities.

## ⚠️ IMPORTANT: User Consent Required

```
╔═══════════════════════════════════════════════════════════════════╗
║  🔐 USER CREATION CONSENT REQUIRED                                ║
╠═══════════════════════════════════════════════════════════════════╣
║                                                                   ║
║  This skill will CREATE A TEST USER in your Supabase project.     ║
║                                                                   ║
║  The user will be created with:                                   ║
║  • Email: pentest-[random]@security-audit.local                   ║
║  • Password: Strong random password (32+ chars)                   ║
║  • Purpose: Testing authenticated access vs anonymous             ║
║                                                                   ║
║  At the end of the audit, you will be asked if you want to        ║
║  DELETE the test user (recommended).                              ║
║                                                                   ║
║  Do you authorize the creation of a test user?                    ║
║  Type "yes, create test user" to proceed.                         ║
║                                                                   ║
╚═══════════════════════════════════════════════════════════════════╝
```

**DO NOT proceed without explicit user consent.**

## When to Use This Skill

- After completing anonymous access tests
- To detect IDOR (Insecure Direct Object Reference) vulnerabilities
- To test cross-user data access
- To verify RLS policies work for authenticated users
- To find privilege escalation issues

## Prerequisites

- Signup must be open (or use invite flow)
- Anon key available
- Anonymous audit completed (recommended)

## Why Authenticated Testing Matters

Many vulnerabilities only appear with authentication:

| Vulnerability | Anonymous | Authenticated |
|---------------|-----------|---------------|
| **RLS bypass (no RLS)** | ✓ Detectable | ✓ Detectable |
| **IDOR** | ✗ Not visible | ✓ **Only visible** |
| **Cross-user access** | ✗ Not visible | ✓ **Only visible** |
| **Privilege escalation** | ✗ Not visible | ✓ **Only visible** |
| **Overly permissive RLS** | Partial | ✓ **Full detection** |

## Test User Creation

### Email Format

```
pentest-[8-char-random]@security-audit.local
```

Example: `[email protected]`

### Password Generation

Strong password with:
- 32+ characters
- Uppercase, lowercase, numbers, symbols
- Cryptographically random

Example: `Xk9$mP2#vL5@nQ8&jR4*wY7!hT3%bU6^`

**The password is displayed ONCE and saved to evidence.**

## Tests Performed

### 1. User Creation & Login

```bash
# Create user
curl -X POST "$SUPABASE_URL/auth/v1/signup" \
  -H "apikey: $ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "password": "[STRONG_PASSWORD]"}'

# Login and get JWT
curl -X POST "$SUPABASE_URL/auth/v1/token?grant_type=password" \
  -H "apikey: $ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "password": "[STRONG_PASSWORD]"}'
```

### 2. Authenticated vs Anonymous Comparison

For each table:

| Test | Anonymous | Authenticated | Finding |
|------|-----------|---------------|---------|
| SELECT | 0 rows | 1,247 rows | 🔴 Auth-only exposure |
| Own data | N/A | Only own row | ✅ RLS working |
| Other users' data | N/A | All rows | 🔴 Cross-user access |

### 3. IDOR Testing

```bash
# As test user, try to access other user's data
curl "$SUPABASE_URL/rest/v1/orders?user_id=eq.[OTHER_USER_ID]" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer [TEST_USER_JWT]"

# If returns data: IDOR vulnerability!
```

### 4. Cross-User Access

```bash
# Get test user's ID from JWT
TEST_USER_ID=$(echo $JWT | jq -r '.sub')

# Try to access data belonging to a different user
curl "$SUPABASE_URL/rest/v1/profiles?id=neq.$TEST_USER_ID" \
  -H "Authorization: Bearer [TEST_USER_JWT]"

# If returns other users' profiles: Cross-user access!
```

### 5. Storage with Authentication

```bash
# Test authenticated storage access
curl "$SUPABASE_URL/storage/v1/object/list/documents" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer [TEST_USER_JWT]"

# Compare with anonymous results
```

### 6. Realtime with Authentication

```javascript
// Subscribe to table changes as authenticated user
const channel = supabase.channel('test')
  .on('postgres_changes', {
    event: '*',
    schema: 'public',
    table: 'orders'
  }, payload => console.log(payload))
  .subscribe()

// Does it receive OTHER users' order changes?
```

## Output Format

```
═══════════════════════════════════════════════════════════
 AUTHENTICATED USER AUDIT
═══════════════════════════════════════════════════════════

 ─────────────────────────────────────────────────────────
 Test User Creation
 ─────────────────────────────────────────────────────────

 Status: ✅ User created successfully

 Test User Details:
 ├── Email: [email protected]
 ├── User ID: 550e8400-e29b-41d4-a716-446655440099
 ├── Password: [Saved to evidence - shown once]
 └── JWT obtained: ✅

 ─────────────────────────────────────────────────────────
 Anonymous vs Authenticated Comparison
 ─────────────────────────────────────────────────────────

 Table: users
 ├── Anonymous access: 0 rows
 ├── Authenticated access: 1,247 rows ← ALL USERS!
 └── Status: 🔴 P0 - Data hidden from anon but exposed to any auth user

 Table: orders
 ├── Anonymous access: 0 rows (blocked)
 ├── Authenticated access: 1 row (own orders only)
 └── Status: ✅ RLS working correctly

 Table: profiles
 ├── Anonymous access: 0 rows
 ├── Authenticated access: 1,247 rows ← ALL PROFILES!
 ├── Own profile only expected: ❌ NO
 └── Status: 🔴 P0 - Cross-user profile access

 ─────────────────────────────────────────────────────────
 IDOR Testing
 ─────────────────────────────────────────────────────────

 Test: Access other user's orders by ID
 ├── Request: GET /orders?user_id=eq.[other-user-id]
 ├── Auth: Test user JWT
 ├── Response: 200 OK - 15 orders returned
 └── Status: 🔴 P0 - IDOR VULNERABILITY

 Proof:
 curl "$URL/rest/v1/orders?user_id=eq.other-user-uuid" \
   -H "Authorization: Bearer [test-user-jwt]"
 # Returns orders belonging to other-user-uuid!

 Test: Access admin endpoints
 ├── Request: GET /functions/v1/admin-panel
 ├── Auth: Test user JWT (regular user)
 ├── Response: 200 OK - Admin data returned!
 └── Status: 🔴 P0 - PRIVILEGE ESCALATION

 ─────────────────────────────────────────────────────────
 Storage with Authentication
 ─────────────────────────────────────────────────────────

 Bucket: documents
 ├── Anonymous: ❌ 0 files (blocked)
 ├── Authenticated: ✅ 523 files visible ← ALL USERS' FILES!
 └── Status: 🔴 P1 - Auth users see all documents

 Bucket: user-uploads
 ├── Anonymous: ❌ 0 files
 ├── Authenticated: 3 files (own files only)
 └── Status: ✅ RLS working correctly

 ─────────────────────────────────────────────────────────
 Summary
 ─────────────────────────────────────────────────────────

 New Findings (Auth-only):
 ├── 🔴 P0: users table - all users visible to any auth user
 ├── 🔴 P0: profiles table - cross-user access
 ├── 🔴 P0: IDOR in orders - can access any user's orders
 ├── 🔴 P0: Privilege escalation in admin-panel
 └── 🟠 P1: documents bucket - all files visible to auth users

 Comparison:
 ├── Issues found (Anonymous): 3
 ├── Issues found (Authenticated): 8 ← 5 NEW ISSUES!
 └── Auth-only vulnerabilities: 5

 Recommendation:
 These issues were NOT visible in anonymous testing!
 Always test with authenticated users.

 ─────────────────────────────────────────────────────────
 Cleanup
 ─────────────────────────────────────────────────────────

 ⚠️  Test user still exists in database.

 Do you want to delete the test user?
 Email: [email protected]

 [This requires service_role key or manual deletion]

═══════════════════════════════════════════════════════════
```

## Context Output

```json
{
  "authenticated_audit": {
    "timestamp": "2025-01-31T12:00:00Z",
    "test_user": {
      "email": "[email protected]",
      "user_id": "550e8400-e29b-41d4-a716-446655440099",
      "created_at": "2025-01-31T12:00:00Z",
      "deleted": false
    },
    "comparison": {
      "tables": {
        "users": {
          "anon_access": 0,
          "auth_access": 1247,
          "expected_auth_access": "own_row_only",
          "severity": "P0",
          "finding": "All users visible to any authenticated user"
        },
        "orders": {
          "anon_access": 0,
          "auth_access": 1,
          "expected_auth_access": "own_rows_only",
          "severity": null,
          "finding": "RLS working correctly"
        }
      },
      "idor_tests": [
        {
          "test": "access_other_user_orders",
          "vulnerable": true,
          "severity": "P0",
          "proof": "curl command..."
        }
      ],
      "privilege_escalation": [
        {
          "endpoint": "/functions/v1/admin-panel",
          "vulnerable": true,
          "severity": "P0"
        }
      ]
    },
    "summary": {
      "anon_issues": 3,
      "auth_issues": 8,
      "auth_only_issues": 5
    }
  }
}
```

## RLS Policy Examples

### Correct: Users see only their own data

```sql
-- This RLS policy is correct
CREATE POLICY "Users see own data"
  ON users FOR SELECT
  USING (auth.uid() = id);

-- Result:
-- Anonymous: 0 rows
-- Authenticated: 1 row (own data)
```

### Incorrect: All authenticated users see everything

```sql
-- This RLS policy is WRONG
CREATE POLICY "Authenticated users see all"
  ON users FOR SELECT
  USING (auth.role() = 'authenticated');  -- ❌ Too permissive!

-- Result:
-- Anonymous: 0 rows
-- Authenticated: ALL rows ← VULNERABILITY!
```

### Correct fix:

```sql
-- Fix: Add user ownership check
CREATE POLICY "Users see own data"
  ON users FOR SELECT
  USING (auth.uid() = id);  -- ✅ Only own row
```

## Cleanup Options

### Option 1: Manual deletion (Dashboard)

```
Supabase Dashboard → Authentication → Users → Find test user → Delete
```

### Option 2: Via service_role key (if available)

```bash
curl -X DELETE "$SUPABASE_URL/auth/v1/admin/users/[USER_ID]" \
  -H "apikey: $SERVICE_ROLE_KEY" \
  -H "Authorization: Bearer $SERVICE_ROLE_KEY"
```

### Option 3: Leave for later

The test user uses a non-functional email domain (`security-audit.local`) and cannot be used maliciously.

## MANDATORY: Evidence Collection

📁 **Evidence Directory:** `.sb-pentest-evidence/05-auth-audit/authenticated-tests/`

### Evidence Files to Create

| File | Content |
|------|---------|
| `test-user-created.json` | Test user details (password saved securely) |
| `anon-vs-auth-comparison.json` | Side-by-side comparison |
| `idor-tests/[table].json` | IDOR test results |
| `privilege-escalation.json` | Privilege escalation tests |

### Evidence Format

```json
{
  "evidence_id": "AUTH-TEST-001",
  "timestamp": "2025-01-31T12:00:00Z",
  "category": "auth-audit",
  "type": "authenticated_testing",

  "test_user": {
    "email": "[email protected]",
    "user_id": "550e8400-...",
    "password": "[STORED SECURELY - DO NOT COMMIT]"
  },

  "comparison_test": {
    "table": "users",
    "anonymous": {
      "curl_command": "curl '$URL/rest/v1/users' -H 'apikey: $ANON_KEY'",
      "response_status": 200,
      "rows_returned": 0
    },
    "authenticated": {
      "curl_command": "curl '$URL/rest/v1/users' -H 'apikey: $ANON_KEY' -H 'Authorization: Bearer $JWT'",
      "response_status": 200,
      "rows_returned": 1247
    },
    "finding": {
      "severity": "P0",
      "issue": "All users visible to any authenticated user",
      "expected": "Only own row should be visible",
      "impact": "Full user enumeration for any authenticated user"
    }
  }
}
```

### Add to curl-commands.sh

```bash
# === AUTHENTICATED TESTING ===
# NOTE: Replace [JWT] with test user's JWT

# Compare anonymous vs authenticated access
curl -s "$SUPABASE_URL/rest/v1/users?select=*&limit=5" -H "apikey: $ANON_KEY"
curl -s "$SUPABASE_URL/rest/v1/users?select=*&limit=5" -H "apikey: $ANON_KEY" -H "Authorization: Bearer [JWT]"

# IDOR test - access other user's data
curl -s "$SUPABASE_URL/rest/v1/orders?user_id=eq.[OTHER_USER_ID]" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer [JWT]"

# Cross-user profile access
curl -s "$SUPABASE_URL/rest/v1/profiles?id=neq.[TEST_USER_ID]" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer [JWT]"
```

## 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 user creation** → Log consent and action to `.sb-pentest-audit.log`
2. **After user created** → Immediately save user details to context and evidence
3. **After each comparison test** → Update `.sb-pentest-context.json` with results
4. **After each IDOR test** → Save evidence immediately

This ensures that if the skill is interrupted, crashes, or times out, all findings up to that point are preserved.

### Required Actions (Progressive)

1. **Log user creation:**
   ```
   [TIMESTAMP] [supabase-audit-authenticated] [CONSENT] User authorized test user creation
   [TIMESTAMP] [supabase-audit-authenticated] [CREATED] Test user [email protected]
   ```

2. **Save test user to context immediately:**
   ```json
   {
     "authenticated_audit": {
       "test_user": {
         "email": "...",
         "user_id": "...",
         "created_at": "..."
       }
     }
   }
   ```

3. **Log each finding as discovered:**
   ```
   [TIMESTAMP] [supabase-audit-authenticated] [FINDING] P0: IDOR in orders table
   ```

**FAILURE TO UPDATE CONTEXT FILES PROGRESSIVELY IS NOT ACCEPTABLE.**

## Related Skills

- `supabase-audit-auth-signup` — Test if signup is open first
- `supabase-audit-tables-read` — Compare with anonymous results
- `supabase-audit-rls` — Deep dive into RLS policies
- `supabase-audit-functions` — Test function access with auth
- `supabase-report` — Include auth-only findings in report

© yoanbernabeu · MIT · yoanbernabeu/supabase-pentest-skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой