home / skills / yoanbernabeu / supabase-pentest-skills / supabase-audit-auth-signup

supabase-audit-auth-signup skill

/skills/audit-auth/supabase-audit-auth-signup

This skill tests signup open/blocked and detects abuse vectors in registration, providing actionable findings for Supabase authentication security.

npx playbooks add skill yoanbernabeu/supabase-pentest-skills --skill supabase-audit-auth-signup

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
13.4 KB
---
name: supabase-audit-auth-signup
description: Test if user signup is open and identify potential abuse vectors in the registration process.
---

# Signup Flow 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 completed**
> - Log to `.sb-pentest-audit.log` **BEFORE and AFTER each test**
> - **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 tests the user registration flow for security issues and misconfigurations.

## When to Use This Skill

- To verify if signup is appropriately restricted
- To test for signup abuse vectors
- To check rate limiting on registration
- As part of authentication security audit

## Prerequisites

- Supabase URL and anon key available
- Auth config audit completed (recommended)

## Why Signup Security Matters

Open signup can lead to:

| Risk | Description |
|------|-------------|
| Spam accounts | Bots creating fake accounts |
| Resource abuse | Free tier exploitation |
| Email spam | Using your service to send emails |
| Data pollution | Fake data in your database |
| Attack surface | More accounts = more attack vectors |

## Tests Performed

| Test | Purpose |
|------|---------|
| Signup availability | Is registration open? |
| Email validation | Does it accept invalid emails? |
| Rate limiting | Can we create many accounts? |
| Disposable emails | Are temp emails blocked? |
| Password policy | What passwords are accepted? |
| Response information | What info is leaked? |

## Usage

### Basic Signup Test

```
Test signup security on my Supabase project
```

### Check Specific Aspects

```
Test if disposable emails are blocked for signup
```

## Output Format

```
═══════════════════════════════════════════════════════════
 SIGNUP FLOW AUDIT
═══════════════════════════════════════════════════════════

 Project: abc123def.supabase.co
 Endpoint: /auth/v1/signup

 ─────────────────────────────────────────────────────────
 Signup Availability
 ─────────────────────────────────────────────────────────

 Status: āœ… OPEN (Anyone can register)

 Test Result:
 POST /auth/v1/signup
 Body: {"email": "[email protected]", "password": "TestPass123!"}
 Response: 200 OK - Account created

 Assessment: Signup is publicly available.
             Review if this is intended.

 ─────────────────────────────────────────────────────────
 Email Validation
 ─────────────────────────────────────────────────────────

 Valid email formats:
 ā”œā”€ā”€ [email protected]: āœ… Accepted (expected)
 ā”œā”€ā”€ [email protected]: āœ… Accepted (expected)
 └── [email protected]: āœ… Accepted (expected)

 Invalid email formats:
 ā”œā”€ā”€ user@: āŒ Rejected (good)
 ā”œā”€ā”€ @domain.com: āŒ Rejected (good)
 ā”œā”€ā”€ [email protected]: āŒ Rejected (good)
 └── not-an-email: āŒ Rejected (good)

 Disposable Email Test:
 ā”œā”€ā”€ [email protected]: āœ… Accepted ← 🟠 P2
 ā”œā”€ā”€ [email protected]: āœ… Accepted ← 🟠 P2
 └── [email protected]: āœ… Accepted ← 🟠 P2

 Finding: Disposable emails are not blocked.
 Risk: Users can create throwaway accounts.

 Recommendation: Consider using an email validation
 service or blocklist in your application logic.

 ─────────────────────────────────────────────────────────
 Password Policy
 ─────────────────────────────────────────────────────────

 Minimum Length Test:
 ā”œā”€ā”€ "12345" (5 chars): āŒ Rejected
 ā”œā”€ā”€ "123456" (6 chars): āœ… Accepted ← P2 Short
 └── "1234567890" (10 chars): āœ… Accepted

 Current Policy: Minimum 6 characters

 Weak Password Test:
 ā”œā”€ā”€ "password": āœ… Accepted ← 🟠 P2
 ā”œā”€ā”€ "123456": āœ… Accepted ← 🟠 P2
 ā”œā”€ā”€ "qwerty123": āœ… Accepted ← 🟠 P2
 └── "letmein": āœ… Accepted ← 🟠 P2

 Finding: Common weak passwords are accepted.

 Recommendation:
 1. Increase minimum length to 8+ characters
 2. Consider password strength requirements
 3. Check against common password lists

 ─────────────────────────────────────────────────────────
 Rate Limiting
 ─────────────────────────────────────────────────────────

 Signup Rate Test (same IP):
 ā”œā”€ā”€ Request 1: āœ… 200 OK
 ā”œā”€ā”€ Request 2: āœ… 200 OK
 ā”œā”€ā”€ Request 3: āœ… 200 OK
 ā”œā”€ā”€ Request 4: āŒ 429 Too Many Requests
 └── Retry-After: 3600 seconds

 Rate Limit: 3 signups/hour per IP
 Assessment: āœ… Rate limiting is active (good)

 ─────────────────────────────────────────────────────────
 Information Disclosure
 ─────────────────────────────────────────────────────────

 Existing Email Test:
 POST /auth/v1/signup (with existing email)
 Response: "User already registered"

 Finding: 🟠 P2 - Response reveals email existence

 This allows:
 ā”œā”€ā”€ Email enumeration attacks
 ā”œā”€ā”€ Knowing if someone has an account
 └── Targeted phishing attempts

 Recommendation: Use generic message like
 "Check your email to continue" for both new
 and existing accounts.

 ─────────────────────────────────────────────────────────
 Email Confirmation
 ─────────────────────────────────────────────────────────

 Status: āŒ NOT REQUIRED (confirmed in auth-config)

 Test: Created account and checked session
 Result: User immediately authenticated without
         email confirmation.

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

 Signup: Open to public
 Rate Limiting: āœ… Active (3/hour)
 Email Confirmation: āŒ Not required

 Findings:
 ā”œā”€ā”€ P1: Email confirmation disabled
 ā”œā”€ā”€ P2: Disposable emails accepted
 ā”œā”€ā”€ P2: Weak passwords accepted
 └── P2: Email enumeration possible

 Security Score: 5/10

 Priority Actions:
 1. Enable email confirmation
 2. Strengthen password policy
 3. Consider disposable email blocking
 4. Use generic error messages

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

## Test Details

### Disposable Email Detection

Common disposable email domains tested:
- mailinator.com
- tempmail.com
- guerrillamail.com
- 10minutemail.com
- throwaway.email

### Weak Password List

Common passwords tested:
- password, password123
- 123456, 12345678
- qwerty, qwerty123
- letmein, welcome
- admin, administrator

### Rate Limit Testing

```
Attempt 1: 200 OK
Attempt 2: 200 OK
Attempt 3: 200 OK
Attempt 4: 429 Too Many Requests
```

## Context Output

```json
{
  "signup_audit": {
    "timestamp": "2025-01-31T13:00:00Z",
    "signup_open": true,
    "rate_limit": {
      "enabled": true,
      "limit": 3,
      "period": "hour"
    },
    "email_validation": {
      "basic_validation": true,
      "disposable_blocked": false
    },
    "password_policy": {
      "min_length": 6,
      "weak_passwords_blocked": false
    },
    "information_disclosure": {
      "email_enumeration": true
    },
    "findings": [
      {
        "severity": "P1",
        "issue": "Email confirmation disabled"
      },
      {
        "severity": "P2",
        "issue": "Disposable emails accepted"
      },
      {
        "severity": "P2",
        "issue": "Weak passwords accepted"
      },
      {
        "severity": "P2",
        "issue": "Email enumeration possible"
      }
    ]
  }
}
```

## Remediation Examples

### Block Disposable Emails

```typescript
// In your signup handler or Edge Function
import { isDisposable } from 'email-validator-package';

if (isDisposable(email)) {
  throw new Error('Please use a permanent email address');
}
```

### Strengthen Password Requirements

```typescript
// Custom password validation
function validatePassword(password: string): boolean {
  if (password.length < 8) return false;
  if (!/[A-Z]/.test(password)) return false;
  if (!/[a-z]/.test(password)) return false;
  if (!/[0-9]/.test(password)) return false;
  return true;
}
```

### Prevent Email Enumeration

```typescript
// Always return same message
async function signup(email, password) {
  try {
    await supabase.auth.signUp({ email, password });
  } catch (error) {
    // Don't reveal if email exists
  }
  return { message: 'Check your email to continue' };
}
```

### Restrict Signup

If signup should be invite-only:

```typescript
// Use admin API to invite users
const { data, error } = await supabaseAdmin.auth.admin.inviteUserByEmail(
  '[email protected]'
);

// Or disable signup in dashboard and use:
const { data, error } = await supabaseAdmin.auth.admin.createUser({
  email: '[email protected]',
  email_confirm: true
});
```

## 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 each signup test** → Log the action to `.sb-pentest-audit.log`
2. **After each vulnerability found** → Immediately update `.sb-pentest-context.json`
3. **After rate limit tests** → Log the results 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. **Update `.sb-pentest-context.json`** with results:
   ```json
   {
     "signup_audit": {
       "timestamp": "...",
       "signup_open": true,
       "rate_limit": { ... },
       "findings": [ ... ]
     }
   }
   ```

2. **Log to `.sb-pentest-audit.log`**:
   ```
   [TIMESTAMP] [supabase-audit-auth-signup] [START] Testing signup security
   [TIMESTAMP] [supabase-audit-auth-signup] [FINDING] P2: Weak passwords accepted
   [TIMESTAMP] [supabase-audit-auth-signup] [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/05-auth-audit/signup-tests/`

### Evidence Files to Create

| File | Content |
|------|---------|
| `signup-tests/open-signup.json` | Signup availability test |
| `signup-tests/weak-password.json` | Weak password acceptance test |
| `signup-tests/disposable-email.json` | Disposable email test |
| `signup-tests/rate-limit.json` | Rate limiting test |

### Evidence Format

```json
{
  "evidence_id": "AUTH-SIGNUP-001",
  "timestamp": "2025-01-31T10:55:00Z",
  "category": "auth-audit",
  "type": "signup_test",

  "tests": [
    {
      "test_name": "weak_password_acceptance",
      "severity": "P2",
      "request": {
        "method": "POST",
        "url": "https://abc123def.supabase.co/auth/v1/signup",
        "body": {"email": "[email protected]", "password": "123456"},
        "curl_command": "curl -X POST '$URL/auth/v1/signup' -H 'apikey: $ANON_KEY' -H 'Content-Type: application/json' -d '{\"email\": \"[email protected]\", \"password\": \"123456\"}'"
      },
      "response": {
        "status": 200,
        "message": "User created"
      },
      "result": "VULNERABLE",
      "impact": "Weak passwords (6 chars) accepted"
    },
    {
      "test_name": "disposable_email",
      "severity": "P2",
      "request": {
        "body": {"email": "[email protected]", "password": "Test123456!"}
      },
      "response": {
        "status": 200,
        "message": "User created"
      },
      "result": "VULNERABLE",
      "impact": "Disposable emails not blocked"
    }
  ]
}
```

## Related Skills

- `supabase-audit-auth-config` — Full auth configuration
- `supabase-audit-auth-users` — User enumeration testing
- `supabase-audit-rls` — Protect user data with RLS

Overview

This skill tests whether user signup is open and identifies abuse vectors in the registration process for Supabase projects. It performs pragmatic checks like disposable email acceptance, password policy strength, rate limiting, and information leakage. Results are saved progressively to context and log files and structured evidence is written for each test.

How this skill works

The skill issues controlled signup requests to the Supabase auth endpoint and evaluates responses for acceptance, error messages, and rate limiting behavior. It classifies findings (e.g., open signup, disposable emails allowed, weak passwords accepted, email enumeration) and writes interim results to .sb-pentest-context.json and .sb-pentest-audit.log after each test. Final evidence files are emitted into .sb-pentest-evidence/05-auth-audit/signup-tests/ for later review.

When to use it

  • During an authentication security audit of a Supabase project
  • When verifying whether signup should be public or restricted
  • To check if disposable emails or weak passwords are accepted
  • To confirm rate limiting is active on registrations
  • Before deployment or when investigating account-creation abuse

Best practices

  • Write context and logs progressively: update context file and audit log immediately after each test
  • Collect structured evidence files for each test case under the evidence directory
  • Use generic response messages on signup to prevent email enumeration
  • Enforce email confirmation and stronger password requirements (min 8+, mixed classes)
  • Block or flag disposable email domains and apply server-side rate limits

Example use cases

  • Confirm whether the project allows anyone to register without invitation
  • Test if common disposable email providers can create accounts
  • Verify password policies by attempting common weak passwords
  • Measure how many signups succeed before a rate limit triggers
  • Detect if signup responses reveal whether an email already exists

FAQ

What evidence files are produced?

The skill creates JSON evidence files for open-signup, weak-password, disposable-email, and rate-limit tests under .sb-pentest-evidence/05-auth-audit/signup-tests/.

Do I need credentials to run the tests?

You need the Supabase URL and anon key to call the public auth endpoints; admin credentials are only required for invite-only remediation actions.

How are discoveries saved if the run is interrupted?

Findings and test logs are written progressively to .sb-pentest-context.json and .sb-pentest-audit.log after each test so partial results are preserved.