supabase-audit-auth-signup by yoanbernabeu/supabase-pentest-skills
npx skills add https://github.com/yoanbernabeu/supabase-pentest-skills --skill supabase-audit-auth-signup🔴 关键:需要渐进式文件更新
你必须在测试过程中就写入上下文文件,而不仅仅是最后才写。
- 每次测试完成后立即写入
.sb-pentest-context.json- 每次测试前后都记录到
.sb-pentest-audit.log- 不要等到技能完成才更新文件
- 如果技能崩溃或被中断,所有之前的发现必须已经保存
这不是可选项。未能渐进式写入是关键错误。
此技能测试用户注册流程是否存在安全问题和配置错误。
开放的注册可能导致:
| 风险 |
|---|
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 描述 |
|---|
| 垃圾账户 | 机器人创建虚假账户 |
| 资源滥用 | 免费层被利用 |
| 垃圾邮件 | 利用你的服务发送邮件 |
| 数据污染 | 数据库中出现虚假数据 |
| 攻击面扩大 | 更多账户意味着更多攻击途径 |
| 测试 | 目的 |
|---|---|
| 注册可用性 | 注册是否开放? |
| 电子邮件验证 | 是否接受无效电子邮件? |
| 速率限制 | 能否创建多个账户? |
| 一次性电子邮件 | 临时邮件是否被阻止? |
| 密码策略 | 接受哪些密码? |
| 响应信息 | 泄露了哪些信息? |
在我的 Supabase 项目上测试注册安全性
测试注册时是否阻止一次性电子邮件
═══════════════════════════════════════════════════════════
注册流程审计
═══════════════════════════════════════════════════════════
项目:abc123def.supabase.co
端点:/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 请求过多
└── 重试等待时间:3600秒
速率限制:每个IP每小时3次注册
评估:✅ 速率限制已启用(良好)
─────────────────────────────────────────────────────────
信息泄露
─────────────────────────────────────────────────────────
现有电子邮件测试:
POST /auth/v1/signup(使用现有电子邮件)
响应:"用户已注册"
发现:🟠 P2 - 响应揭示了电子邮件是否存在
这允许:
├── 电子邮件枚举攻击
├── 知道某人是否有账户
└── 有针对性的钓鱼尝试
建议:对新账户和现有账户都使用
通用消息,如"请检查您的电子邮件以继续"。
─────────────────────────────────────────────────────────
电子邮件确认
─────────────────────────────────────────────────────────
状态:❌ 不需要(在auth-config中确认)
测试:创建账户并检查会话
结果:用户立即通过身份验证,无需
电子邮件确认。
─────────────────────────────────────────────────────────
总结
─────────────────────────────────────────────────────────
注册:对公众开放
速率限制:✅ 已启用(3次/小时)
电子邮件确认:❌ 不需要
发现:
├── P1:电子邮件确认已禁用
├── P2:接受一次性电子邮件
├── P2:接受弱密码
└── P2:可能进行电子邮件枚举
安全评分:5/10
优先行动:
1. 启用电子邮件确认
2. 加强密码策略
3. 考虑阻止一次性电子邮件
4. 使用通用错误消息
═══════════════════════════════════════════════════════════
测试的常见一次性电子邮件域名:
测试的常见密码:
尝试1:200 OK
尝试2:200 OK
尝试3:200 OK
尝试4:429 请求过多
{
"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"
}
]
}
}
// 在你的注册处理程序或 Edge Function 中
import { isDisposable } from 'email-validator-package';
if (isDisposable(email)) {
throw new Error('Please use a permanent email address');
}
// 自定义密码验证
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;
}
// 始终返回相同的消息
async function signup(email, password) {
try {
await supabase.auth.signUp({ email, password });
} catch (error) {
// 不要揭示电子邮件是否存在
}
return { message: 'Check your email to continue' };
}
如果注册应该是仅限邀请:
// 使用管理员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
});
⚠️ 此技能必须在执行过程中渐进式更新跟踪文件,而不仅仅是在最后。
不要在最后批量写入所有内容。而是:
.sb-pentest-audit.log.sb-pentest-context.json这确保了如果技能被中断、崩溃或超时,所有到该点为止的发现都被保留。
更新 .sb-pentest-context.json 并包含结果:
{ "signup_audit": { "timestamp": "...", "signup_open": true, "rate_limit": { ... }, "findings": [ ... ] } }
记录到 .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
如果文件不存在,在写入前创建它们。
未能更新上下文文件是不可接受的。
📁 证据目录: .sb-pentest-evidence/05-auth-audit/signup-tests/
| 文件 | 内容 |
|---|---|
signup-tests/open-signup.json | 注册可用性测试 |
signup-tests/weak-password.json | 弱密码接受测试 |
signup-tests/disposable-email.json | 一次性电子邮件测试 |
signup-tests/rate-limit.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"
}
]
}
supabase-audit-auth-config — 完整的身份验证配置supabase-audit-auth-users — 用户枚举测试supabase-audit-rls — 使用RLS保护用户数据每周安装次数
93
仓库
GitHub星标数
33
首次出现
2026年1月31日
安全审计
安装在
claude-code75
codex69
opencode68
gemini-cli65
github-copilot60
cursor60
🔴 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 RLSWeekly Installs
93
Repository
GitHub Stars
33
First Seen
Jan 31, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code75
codex69
opencode68
gemini-cli65
github-copilot60
cursor60
Supabase Postgres 最佳实践指南 - 8大类别性能优化规则与SQL示例
78,800 周安装