supabase-audit-auth-signup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

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.
🔴 CRITICAL: PROGRESSIVE FILE UPDATES REQUIRED
你必须逐步写入上下文文件,而不是仅在最后统一写入。
  • 每次测试完成后立即写入
    .sb-pentest-context.json
  • 每次测试前后都要记录到
    .sb-pentest-audit.log
  • 不要等到技能执行完毕再更新文件
  • 如果技能崩溃或被中断,所有已发现的结果必须已保存
此要求为强制性,未逐步写入属于严重错误。
本技能用于测试用户注册流程中的安全问题和配置错误。

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)
  • 已获取Supabase URL和anon key
  • 已完成Auth配置审计(推荐)

Why Signup Security Matters

注册安全的重要性

Open signup can lead to:
RiskDescription
Spam accountsBots creating fake accounts
Resource abuseFree tier exploitation
Email spamUsing your service to send emails
Data pollutionFake data in your database
Attack surfaceMore accounts = more attack vectors
开放注册可能导致以下风险:
风险描述
垃圾账号机器人创建虚假账号
资源滥用免费套餐被恶意利用
邮件垃圾利用你的服务发送垃圾邮件
数据污染数据库中混入虚假数据
攻击面扩大账号越多,潜在攻击点越多

Tests Performed

执行的测试

TestPurpose
Signup availabilityIs registration open?
Email validationDoes it accept invalid emails?
Rate limitingCan we create many accounts?
Disposable emailsAre temp emails blocked?
Password policyWhat passwords are accepted?
Response informationWhat info is leaked?
测试项目的
注册可用性注册是否开放?
邮箱验证是否接受无效邮箱?
速率限制是否可以批量创建账号?
临时邮箱检测是否拦截临时邮箱?
密码策略允许使用哪些密码?
响应信息泄露泄露了哪些敏感信息?

Usage

使用方法

Basic Signup Test

基础注册测试

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

Check Specific Aspects

检查特定维度

Test if disposable emails are blocked for signup
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": "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

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

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

 ─────────────────────────────────────────────────────────
 注册可用性
 ─────────────────────────────────────────────────────────

 状态: ✅ 开放(任何人可注册)

 测试结果:
 POST /auth/v1/signup
 请求体: {"email": "test-xxxxx@example.com", "password": "TestPass123!"}
 响应: 200 OK - 账号创建成功

 评估: 注册对公众开放。请确认是否为预期配置。

 ─────────────────────────────────────────────────────────
 邮箱验证
 ─────────────────────────────────────────────────────────

 有效邮箱格式:
 ├── user@domain.com: ✅ 被接受(符合预期)
 ├── user+tag@domain.com: ✅ 被接受(符合预期)
 └── user@subdomain.domain.com: ✅ 被接受(符合预期)

 无效邮箱格式:
 ├── user@: ❌ 被拒绝(安全)
 ├── @domain.com: ❌ 被拒绝(安全)
 ├── user@.com: ❌ 被拒绝(安全)
 └── not-an-email: ❌ 被拒绝(安全)

 临时邮箱测试:
 ├── user@mailinator.com: ✅ 被接受 ← 🟠 P2
 ├── user@tempmail.com: ✅ 被接受 ← 🟠 P2
 └── user@guerrillamail.com: ✅ 被接受 ← 🟠 P2

 发现问题: 未拦截临时邮箱。
 风险: 用户可创建一次性账号。

 建议: 考虑使用邮箱验证服务或在应用逻辑中添加拦截名单。

 ─────────────────────────────────────────────────────────
 密码策略
 ─────────────────────────────────────────────────────────

 最小长度测试:
 ├── "12345"(5位): ❌ 被拒绝
 ├── "123456"(6位): ✅ 被接受 ← P2 过短
 └── "1234567890"(10位): ✅ 被接受

 当前策略: 最小6位字符

 弱密码测试:
 ├── "password": ✅ 被接受 ← 🟠 P2
 ├── "123456": ✅ 被接受 ← 🟠 P2
 ├── "qwerty123": ✅ 被接受 ← 🟠 P2
 └── "letmein": ✅ 被接受 ← 🟠 P2

 发现问题: 允许使用常见弱密码。

 建议:
 1. 将最小长度提升至8位以上
 2. 考虑添加密码强度要求
 3. 校验密码是否在常见弱密码列表中

 ─────────────────────────────────────────────────────────
 速率限制
 ─────────────────────────────────────────────────────────

 同IP注册速率测试:
 ├── 请求1: ✅ 200 OK
 ├── 请求2: ✅ 200 OK
 ├── 请求3: ✅ 200 OK
 ├── 请求4: ❌ 429 Too Many Requests
 └── Retry-After: 3600秒

 速率限制: 每IP每小时3次注册
 评估: ✅ 速率限制已启用(安全)

 ─────────────────────────────────────────────────────────
 信息泄露
 ─────────────────────────────────────────────────────────

 已存在邮箱测试:
 POST /auth/v1/signup(使用已注册邮箱)
 响应: "User already registered"

 发现问题: 🟠 P2 - 响应泄露邮箱已注册

 风险:
 ├── 邮箱枚举攻击
 ├── 可判断特定用户是否拥有账号
 └── 针对性钓鱼攻击

 建议: 对新账号和已存在账号均返回通用提示,例如
 "请检查邮箱以继续操作"

 ─────────────────────────────────────────────────────────
 邮箱确认
 ─────────────────────────────────────────────────────────

 状态: ❌ 未要求(在auth-config中已确认)

 测试: 创建账号并检查会话
 结果: 用户无需邮箱确认即可立即登录。

 ─────────────────────────────────────────────────────────
 总结
 ─────────────────────────────────────────────────────────

 注册状态: 对公众开放
 速率限制: ✅ 已启用(3次/小时)
 邮箱确认: ❌ 未要求

 发现问题:
 ├── P1: 邮箱确认已禁用
 ├── P2: 允许使用临时邮箱
 ├── P2: 允许使用弱密码
 └── P2: 存在邮箱枚举风险

 安全评分: 5/10

 优先修复项:
 1. 启用邮箱确认
 2. 强化密码策略
 3. 考虑拦截临时邮箱
 4. 使用通用错误提示

═══════════════════════════════════════════════════════════

Test Details

测试细节

Disposable Email Detection

临时邮箱检测

Common disposable email domains tested:
  • mailinator.com
  • tempmail.com
  • guerrillamail.com
  • 10minutemail.com
  • throwaway.email
测试的常见临时邮箱域名:
  • 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
测试的常见弱密码:
  • 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
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"
      }
    ]
  }
}
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');
}
typescript
// 在注册处理函数或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;
}
typescript
// 自定义密码验证
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' };
}
typescript
// 始终返回相同提示
async function signup(email, password) {
  try {
    await supabase.auth.signUp({ email, password });
  } catch (error) {
    // 不泄露邮箱是否已存在
  }
  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(
  '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
});
如果注册应为邀请制:
typescript
// 使用管理员API邀请用户
const { data, error } = await supabaseAdmin.auth.admin.inviteUserByEmail(
  'user@example.com'
);

// 或在控制台禁用注册后使用:
const { data, error } = await supabaseAdmin.auth.admin.createUser({
  email: 'user@example.com',
  email_confirm: true
});

MANDATORY: Progressive Context File Updates

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.
不要批量写入所有内容。请遵循:
  1. 每次注册测试前 → 将操作记录到
    .sb-pentest-audit.log
  2. 每次发现漏洞后 → 立即更新
    .sb-pentest-context.json
  3. 速率限制测试完成后 → 立即记录结果
这样可确保如果技能被中断、崩溃或超时,截至当前的所有发现都已被保存。

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.
  1. 更新
    .sb-pentest-context.json
    记录结果:
    json
    {
      "signup_audit": {
        "timestamp": "...",
        "signup_open": true,
        "rate_limit": { ... },
        "findings": [ ... ]
      }
    }
  2. 记录到
    .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. 如果文件不存在,在写入前先创建。
未更新上下文文件的行为是不被接受的。

MANDATORY: Evidence Collection

MANDATORY: Evidence Collection

📁 Evidence Directory:
.sb-pentest-evidence/05-auth-audit/signup-tests/
📁 证据目录:
.sb-pentest-evidence/05-auth-audit/signup-tests/

Evidence Files to Create

需要创建的证据文件

FileContent
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
文件内容
signup-tests/open-signup.json
注册可用性测试结果
signup-tests/weak-password.json
弱密码接受测试结果
signup-tests/disposable-email.json
临时邮箱测试结果
signup-tests/rate-limit.json
速率限制测试结果

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": "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"
    }
  ]
}
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": "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"
    }
  ]
}

Related Skills

相关技能

  • supabase-audit-auth-config
    — Full auth configuration
  • supabase-audit-auth-users
    — User enumeration testing
  • supabase-audit-rls
    — Protect user data with RLS
  • supabase-audit-auth-config
    — 完整身份验证配置审计
  • supabase-audit-auth-users
    — 用户枚举测试
  • supabase-audit-rls
    — 使用RLS保护用户数据