with one click
supabase-audit-auth-signup
// Test if user signup is open and identify potential abuse vectors in the registration process.
// Test if user signup is open and identify potential abuse vectors in the registration process.
Orchestrate a complete Supabase security audit with guided step-by-step execution and ownership confirmation.
Test Row Level Security (RLS) policies for common bypass vulnerabilities and misconfigurations.
List and test exposed PostgreSQL RPC functions for security issues and potential RLS bypass.
List all tables exposed via the Supabase PostgREST API to identify the attack surface.
Attempt to read data from exposed tables to verify actual data exposure and RLS effectiveness.
Analyze Supabase authentication configuration for security weaknesses and misconfigurations.
| name | supabase-audit-auth-signup |
| description | Test if user signup is open and identify potential abuse vectors in the registration process. |
š“ 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 test completed- Log to
.sb-pentest-audit.logBEFORE 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.
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 |
| 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? |
Test signup security on my Supabase project
Test if disposable emails are blocked for signup
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
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": "test-xxxxx@example.com", "password": "TestPass123!"}
Response: 200 OK - Account created
Assessment: Signup is publicly available.
Review if this is intended.
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Email Validation
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Valid email formats:
āāā user@domain.com: ā
Accepted (expected)
āāā user+tag@domain.com: ā
Accepted (expected)
āāā user@subdomain.domain.com: ā
Accepted (expected)
Invalid email formats:
āāā user@: ā Rejected (good)
āāā @domain.com: ā Rejected (good)
āāā user@.com: ā Rejected (good)
āāā not-an-email: ā Rejected (good)
Disposable Email Test:
āāā user@mailinator.com: ā
Accepted ā š P2
āāā user@tempmail.com: ā
Accepted ā š P2
āāā user@guerrillamail.com: ā
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
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Common disposable email domains tested:
Common passwords tested:
Attempt 1: 200 OK
Attempt 2: 200 OK
Attempt 3: 200 OK
Attempt 4: 429 Too Many Requests
{
"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"
}
]
}
}
// 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');
}
// 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;
}
// 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' };
}
If signup should be invite-only:
// Use admin API to invite users
const { data, error } = await supabaseAdmin.auth.admin.inviteUserByEmail(
'user@example.com'
);
// Or disable signup in dashboard and use:
const { data, error } = await supabaseAdmin.auth.admin.createUser({
email: 'user@example.com',
email_confirm: true
});
ā ļø This skill MUST update tracking files PROGRESSIVELY during execution, NOT just at the end.
DO NOT batch all writes at the end. Instead:
.sb-pentest-audit.log.sb-pentest-context.jsonThis ensures that if the skill is interrupted, crashes, or times out, all findings up to that point are preserved.
Update .sb-pentest-context.json with results:
{
"signup_audit": {
"timestamp": "...",
"signup_open": true,
"rate_limit": { ... },
"findings": [ ... ]
}
}
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
If files don't exist, create them before writing.
FAILURE TO UPDATE CONTEXT FILES IS NOT ACCEPTABLE.
š Evidence Directory: .sb-pentest-evidence/05-auth-audit/signup-tests/
| 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_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": "test@example.com", "password": "123456"},
"curl_command": "curl -X POST '$URL/auth/v1/signup' -H 'apikey: $ANON_KEY' -H 'Content-Type: application/json' -d '{\"email\": \"test@example.com\", \"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": "test@mailinator.com", "password": "Test123456!"}
},
"response": {
"status": 200,
"message": "User created"
},
"result": "VULNERABLE",
"impact": "Disposable emails not blocked"
}
]
}
supabase-audit-auth-config ā Full auth configurationsupabase-audit-auth-users ā User enumeration testingsupabase-audit-rls ā Protect user data with RLS