supabase-extract-db-string
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDatabase Connection String Detection
数据库连接字符串检测
🔴 CRITICAL: PROGRESSIVE FILE UPDATES REQUIREDYou MUST write to context files AS YOU GO, not just at the end.
- Write to
IMMEDIATELY after each discovery.sb-pentest-context.json- Log to
BEFORE and AFTER each action.sb-pentest-audit.log- 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 detects if PostgreSQL database connection strings are accidentally exposed in client-side code.
🔴 严重级别:必须逐步更新文件你必须逐步写入上下文文件,而不是只在最后写入。
- 每次发现后立即写入
.sb-pentest-context.json- 在每次操作前后记录到
.sb-pentest-audit.log- 不要等到技能完成后才更新文件
- 如果技能崩溃或被中断,所有之前的发现必须已保存
这不是可选要求。不逐步写入属于严重错误。
该技能用于检测客户端代码中是否意外暴露了PostgreSQL数据库连接字符串。
When to Use This Skill
何时使用该技能
- As part of every security audit
- When reviewing code before production
- When Supabase database access is suspected
- 作为每次安全审计的一部分
- 上线前审查代码时
- 怀疑Supabase数据库访问存在风险时
Prerequisites
前置条件
- Target application accessible
- Supabase detection completed (auto-invokes if needed)
- 可访问目标应用
- 已完成Supabase检测(如需会自动调用)
Why This Is Critical
为何这至关重要
Exposed database connection strings allow:
| Impact | Description |
|---|---|
| 🔴 Direct DB Access | Bypass API, connect directly to PostgreSQL |
| 🔴 Full Data Access | Read/write all data without RLS |
| 🔴 Schema Access | View and modify database structure |
| 🔴 User Enumeration | Access auth.users table directly |
This is a P0 (Critical) finding requiring immediate action.
暴露的数据库连接字符串会导致:
| 影响 | 描述 |
|---|---|
| 🔴 直接数据库访问 | 绕过API,直接连接PostgreSQL |
| 🔴 全数据访问 | 无需RLS即可读写所有数据 |
| 🔴 架构访问 | 查看并修改数据库结构 |
| 🔴 用户枚举 | 直接访问auth.users表 |
这是需要立即处理的P0(严重)级问题。
Connection String Patterns
连接字符串模式
Supabase Database URL
Supabase数据库URL
postgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgrespostgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgresConnection String Components
连接字符串组件
| Component | Example | Sensitivity |
|---|---|---|
| Host | | Medium |
| Port | | Low |
| Database | | Low |
| Username | | Medium |
| Password | | 🔴 Critical |
| 组件 | 示例 | 敏感度 |
|---|---|---|
| 主机 | | 中等 |
| 端口 | | 低 |
| 数据库 | | 低 |
| 用户名 | | 中等 |
| 密码 | | 🔴 严重 |
Pooler Connection (Supavisor)
池化连接(Supavisor)
postgresql://postgres.[project-ref]:[password]@aws-0-us-east-1.pooler.supabase.com:6543/postgrespostgresql://postgres.[project-ref]:[password]@aws-0-us-east-1.pooler.supabase.com:6543/postgresDetection Patterns
检测模式
1. Full Connection Strings
1. 完整连接字符串
javascript
// ❌ CRITICAL - Full connection string
const dbUrl = 'postgresql://postgres:MySecretPass123@db.abc123.supabase.co:5432/postgres'javascript
// ❌ 严重 - 完整连接字符串
const dbUrl = 'postgresql://postgres:MySecretPass123@db.abc123.supabase.co:5432/postgres'2. Environment Variable Leaks
2. 环境变量泄露
javascript
// ❌ Exposed in client bundle
process.env.DATABASE_URL
process.env.POSTGRES_URL
process.env.SUPABASE_DB_URLjavascript
// ❌ 在客户端包中暴露
process.env.DATABASE_URL
process.env.POSTGRES_URL
process.env.SUPABASE_DB_URL3. Partial Exposure
3. 部分信息暴露
javascript
// ⚠️ Password exposed separately
const DB_PASSWORD = 'MySecretPass123'
const DB_HOST = 'db.abc123.supabase.co'javascript
// ⚠️ 密码单独暴露
const DB_PASSWORD = 'MySecretPass123'
const DB_HOST = 'db.abc123.supabase.co'4. ORM Configuration
4. ORM配置
javascript
// ❌ Database config in client code
const prisma = new PrismaClient({
datasources: {
db: {
url: 'postgresql://postgres:pass@db.abc123.supabase.co:5432/postgres'
}
}
})javascript
// ❌ 客户端代码中的数据库配置
const prisma = new PrismaClient({
datasources: {
db: {
url: 'postgresql://postgres:pass@db.abc123.supabase.co:5432/postgres'
}
}
})Usage
使用方法
Basic Check
基础检查
Check for database connection strings on https://myapp.example.com检查https://myapp.example.com上的数据库连接字符串Deep Scan
深度扫描
Deep scan for DB credentials on https://myapp.example.com对https://myapp.example.com进行深度扫描以查找数据库凭证Output Format
输出格式
No Connection String Found (Good)
未找到连接字符串(正常)
═══════════════════════════════════════════════════════════
DATABASE CONNECTION STRING CHECK
═══════════════════════════════════════════════════════════
Status: ✅ No database connection strings detected
Scanned:
├── JavaScript bundles: 5 files analyzed
├── PostgreSQL patterns: None found
├── Connection strings: None found
└── Password patterns: None found
Result: PASS - No direct database credentials exposed
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
数据库连接字符串检查
═══════════════════════════════════════════════════════════
状态:✅ 未检测到数据库连接字符串
扫描内容:
├── JavaScript包:已分析5个文件
├── PostgreSQL模式:未找到
├── 连接字符串:未找到
└── 密码模式:未找到
结果:通过 - 未暴露直接数据库凭证
═══════════════════════════════════════════════════════════Connection String FOUND (Critical)
找到连接字符串(严重)
═══════════════════════════════════════════════════════════
🔴 CRITICAL: DATABASE CONNECTION STRING EXPOSED
═══════════════════════════════════════════════════════════
Severity: P0 - CRITICAL
Status: ❌ PostgreSQL connection string found in client code!
⚠️ IMMEDIATE ACTION REQUIRED ⚠️
Connection String:
postgresql://postgres:MySecr***@db.abc123def.supabase.co:5432/postgres
(Password partially redacted in display, full value in context file)
Parsed Components:
├── Host: db.abc123def.supabase.co
├── Port: 5432
├── Database: postgres
├── Username: postgres
└── Password: [EXPOSED] ← CRITICAL
Location:
└── /static/js/api.chunk.js (line 234)
const DATABASE_URL = 'postgresql://postgres:...'
Impact Assessment:
├── 🔴 Direct PostgreSQL access possible
├── 🔴 All RLS policies bypassed
├── 🔴 Can access auth.users table
├── 🔴 Can modify database schema
└── 🔴 Full data exfiltration possible
═══════════════════════════════════════════════════════════
IMMEDIATE REMEDIATION STEPS
═══════════════════════════════════════════════════════════
1. CHANGE DATABASE PASSWORD NOW
→ Supabase Dashboard > Settings > Database > Reset database password
2. REMOVE FROM CLIENT CODE
→ Delete connection string from source code
→ Ensure DATABASE_URL is not in NEXT_PUBLIC_* or VITE_* env vars
→ Redeploy application
3. AUDIT FOR ABUSE
→ Check Supabase logs for direct PostgreSQL connections
→ Review for unauthorized data access or modifications
4. USE PROPER ARCHITECTURE
→ Client should ONLY use Supabase client library (REST API)
→ Direct DB access should ONLY be from:
- Edge Functions
- Server-side code
- Migration tools
Documentation:
→ https://supabase.com/docs/guides/database/connecting-to-postgres
→ https://supabase.com/docs/guides/functions
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
🔴 严重:数据库连接字符串已暴露
═══════════════════════════════════════════════════════════
严重级别:P0 - 严重
状态:❌ 在客户端代码中发现PostgreSQL连接字符串!
⚠️ 需立即采取行动 ⚠️
连接字符串:
postgresql://postgres:MySecr***@db.abc123def.supabase.co:5432/postgres
(显示时密码已部分脱敏,完整值已保存到上下文文件)
解析后的组件:
├── 主机:db.abc123def.supabase.co
├── 端口:5432
├── 数据库:postgres
├── 用户名:postgres
└── 密码:[已暴露] ← 严重
位置:
└── /static/js/api.chunk.js(第234行)
const DATABASE_URL = 'postgresql://postgres:...'
影响评估:
├── 🔴 可直接访问PostgreSQL
├── 🔴 所有RLS策略被绕过
├── 🔴 可访问auth.users表
├── 🔴 可修改数据库架构
└── 🔴 可完全泄露数据
═══════════════════════════════════════════════════════════
立即修复步骤
═══════════════════════════════════════════════════════════
1. 立即更改数据库密码
→ Supabase控制台 > 设置 > 数据库 > 重置数据库密码
2. 从客户端代码中移除
→ 从源代码中删除连接字符串
→ 确保DATABASE_URL不在NEXT_PUBLIC_*或VITE_*环境变量中
→ 重新部署应用
3. 审计是否被滥用
→ 检查Supabase日志中的直接PostgreSQL连接记录
→ 审查是否存在未授权的数据访问或修改
4. 使用正确的架构
→ 客户端应仅使用Supabase客户端库(REST API)
→ 仅允许以下场景直接访问数据库:
- Edge Functions
- 服务端代码
- 迁移工具
文档:
→ https://supabase.com/docs/guides/database/connecting-to-postgres
→ https://supabase.com/docs/guides/functions
═══════════════════════════════════════════════════════════Context Output
上下文输出
json
{
"findings": [
{
"id": "DB_CONNECTION_STRING_EXPOSED",
"severity": "P0",
"title": "PostgreSQL Connection String Exposed",
"description": "Database connection string with password found in client-side code",
"location": {
"file": "/static/js/api.chunk.js",
"line": 234
},
"evidence": {
"host": "db.abc123def.supabase.co",
"port": 5432,
"database": "postgres",
"username": "postgres",
"password_exposed": true
},
"remediation": {
"immediate": "Reset database password in Supabase Dashboard",
"long_term": "Move DB operations to Edge Functions",
"docs": "https://supabase.com/docs/guides/database/connecting-to-postgres"
}
}
],
"supabase": {
"db_string_exposed": true,
"db_host": "db.abc123def.supabase.co"
}
}json
{
"findings": [
{
"id": "DB_CONNECTION_STRING_EXPOSED",
"severity": "P0",
"title": "PostgreSQL Connection String Exposed",
"description": "Database connection string with password found in client-side code",
"location": {
"file": "/static/js/api.chunk.js",
"line": 234
},
"evidence": {
"host": "db.abc123def.supabase.co",
"port": 5432,
"database": "postgres",
"username": "postgres",
"password_exposed": true
},
"remediation": {
"immediate": "Reset database password in Supabase Dashboard",
"long_term": "Move DB operations to Edge Functions",
"docs": "https://supabase.com/docs/guides/database/connecting-to-postgres"
}
}
],
"supabase": {
"db_string_exposed": true,
"db_host": "db.abc123def.supabase.co"
}
}Partial Exposure
部分信息暴露
Even partial exposure is concerning:
═══════════════════════════════════════════════════════════
⚠️ PARTIAL DATABASE CREDENTIALS FOUND
═══════════════════════════════════════════════════════════
Severity: P1 - High
Found:
├── Database host: db.abc123def.supabase.co (line 45)
├── Database password: [16 char string] (line 89)
└── Could potentially be combined for access
Recommendation:
→ Rotate database password as precaution
→ Remove all DB-related values from client code
═══════════════════════════════════════════════════════════即使是部分信息暴露也需重视:
═══════════════════════════════════════════════════════════
⚠️ 发现部分数据库凭证
═══════════════════════════════════════════════════════════
严重级别:P1 - 高
发现内容:
├── 数据库主机:db.abc123def.supabase.co(第45行)
├── 数据库密码:[16位字符串](第89行)
└── 这些信息可能被组合用于访问数据库
建议:
→ 作为预防措施,轮换数据库密码
→ 从客户端代码中移除所有与数据库相关的值
═══════════════════════════════════════════════════════════Common Causes
常见原因
| Cause | Solution |
|---|---|
| Wrong env prefix | Never use |
| SSR code in client | Ensure server-only code stays server-side |
| Bundler misconfiguration | Review webpack/vite config for env exposure |
| Copy-paste error | Double-check what you're committing |
| 原因 | 解决方案 |
|---|---|
| 错误的环境变量前缀 | 永远不要使用 |
| SSR代码出现在客户端 | 确保仅服务端代码留在服务端 |
| 打包工具配置错误 | 审查webpack/vite配置中的环境变量暴露情况 |
| 复制粘贴错误 | 仔细检查提交的内容 |
Architecture Guidance
架构指导
Wrong (Direct DB in Client)
错误示例(客户端直接访问数据库)
javascript
// ❌ NEVER in client code
import { Pool } from 'pg'
const pool = new Pool({
connectionString: process.env.DATABASE_URL // ❌
})javascript
// ❌ 绝不能出现在客户端代码中
import { Pool } from 'pg'
const pool = new Pool({
connectionString: process.env.DATABASE_URL // ❌
})Correct (API or Edge Function)
正确示例(API或Edge Function)
javascript
// ✅ Client uses Supabase client
const { data } = await supabase
.from('products')
.select('*')
// OR call an Edge Function for complex queries
const { data } = await supabase.functions.invoke('complex-query')javascript
// ✅ 客户端使用Supabase客户端
const { data } = await supabase
.from('products')
.select('*')
// 或调用Edge Function执行复杂查询
const { data } = await supabase.functions.invoke('complex-query')Edge Function (Server-Side)
Edge Function(服务端)
typescript
// supabase/functions/complex-query/index.ts
import { createClient } from '@supabase/supabase-js'
Deno.serve(async (req) => {
// ✅ Direct DB access only on server
const supabase = createClient(
Deno.env.get('SUPABASE_URL'),
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')
)
// Complex query that can't be done via REST
const { data } = await supabase.rpc('complex_function')
return new Response(JSON.stringify(data))
})typescript
// supabase/functions/complex-query/index.ts
import { createClient } from '@supabase/supabase-js'
Deno.serve(async (req) => {
// ✅ 仅服务端可直接访问数据库
const supabase = createClient(
Deno.env.get('SUPABASE_URL'),
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')
)
// 无法通过REST API完成的复杂查询
const { data } = await supabase.rpc('complex_function')
return new Response(JSON.stringify(data))
})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:
- Before starting any action → Log the action to
.sb-pentest-audit.log - After each discovery → Immediately update
.sb-pentest-context.json - After each significant step → Log completion to
.sb-pentest-audit.log
This ensures that if the skill is interrupted, crashes, or times out, all findings up to that point are preserved.
不要批量在最后写入。而是:
- 开始任何操作前 → 将操作记录到
.sb-pentest-audit.log - 每次发现后 → 立即更新
.sb-pentest-context.json - 完成每个重要步骤后 → 将完成情况记录到
.sb-pentest-audit.log
这样可以确保如果技能被中断、崩溃或超时,截至该点的所有发现都已保存。
Required Actions (Progressive)
强制操作(逐步执行)
-
Updatewith findings:
.sb-pentest-context.jsonjson{ "supabase": { "db_string_exposed": true/false, "db_host": "db.[ref].supabase.co" }, "findings": [ { "id": "DB_CONNECTION_STRING_EXPOSED", "severity": "P0", ... } ] } -
Log to:
.sb-pentest-audit.log[TIMESTAMP] [supabase-extract-db-string] [START] Checking for DB connection strings [TIMESTAMP] [supabase-extract-db-string] [CRITICAL] Connection string EXPOSED [TIMESTAMP] [supabase-extract-db-string] [CONTEXT_UPDATED] .sb-pentest-context.json updated -
If files don't exist, create them before writing.
FAILURE TO UPDATE CONTEXT FILES IS NOT ACCEPTABLE.
-
**更新**以记录发现:
.sb-pentest-context.jsonjson{ "supabase": { "db_string_exposed": true/false, "db_host": "db.[ref].supabase.co" }, "findings": [ { "id": "DB_CONNECTION_STRING_EXPOSED", "severity": "P0", ... } ] } -
记录到:
.sb-pentest-audit.log[TIMESTAMP] [supabase-extract-db-string] [START] 正在检查数据库连接字符串 [TIMESTAMP] [supabase-extract-db-string] [CRITICAL] 连接字符串已暴露 [TIMESTAMP] [supabase-extract-db-string] [CONTEXT_UPDATED] .sb-pentest-context.json已更新 -
如果文件不存在,在写入前创建。
不更新上下文文件是不被允许的。
MANDATORY: Evidence Collection
强制要求:证据收集
📁 Evidence Directory:
.sb-pentest-evidence/02-extraction/db-string-exposure/📁 证据目录:
.sb-pentest-evidence/02-extraction/db-string-exposure/Evidence Files to Create (if DB string found)
需创建的证据文件(如果发现数据库字符串)
| File | Content |
|---|---|
| Parsed connection string (password redacted) |
| File path and line number |
| 文件 | 内容 |
|---|---|
| 解析后的连接字符串(密码已脱敏) |
| 文件路径和行号 |
Evidence Format (P0 Finding)
证据格式(P0级发现)
json
{
"evidence_id": "EXT-DB-001",
"timestamp": "2025-01-31T10:12:00Z",
"category": "extraction",
"type": "db_connection_string",
"severity": "P0",
"finding_id": "P0-002",
"connection_string": {
"pattern": "postgresql://postgres:[REDACTED]@db.abc123def.supabase.co:5432/postgres",
"host": "db.abc123def.supabase.co",
"port": 5432,
"database": "postgres",
"username": "postgres",
"password_exposed": true,
"password_length": 24
},
"location": {
"file": "/static/js/api.chunk.js",
"line": 234,
"context": "const DATABASE_URL = 'postgresql://postgres:...' // [REDACTED]"
},
"impact": {
"direct_db_access": true,
"rls_bypass": true,
"schema_access": true,
"auth_users_access": true
},
"remediation": {
"immediate": "Reset database password in Supabase Dashboard",
"remove_from_code": "Delete DATABASE_URL from client code",
"verify_env_vars": "Ensure not using NEXT_PUBLIC_DATABASE_URL or similar"
}
}json
{
"evidence_id": "EXT-DB-001",
"timestamp": "2025-01-31T10:12:00Z",
"category": "extraction",
"type": "db_connection_string",
"severity": "P0",
"finding_id": "P0-002",
"connection_string": {
"pattern": "postgresql://postgres:[REDACTED]@db.abc123def.supabase.co:5432/postgres",
"host": "db.abc123def.supabase.co",
"port": 5432,
"database": "postgres",
"username": "postgres",
"password_exposed": true,
"password_length": 24
},
"location": {
"file": "/static/js/api.chunk.js",
"line": 234,
"context": "const DATABASE_URL = 'postgresql://postgres:...' // [REDACTED]"
},
"impact": {
"direct_db_access": true,
"rls_bypass": true,
"schema_access": true,
"auth_users_access": true
},
"remediation": {
"immediate": "在Supabase控制台重置数据库密码",
"remove_from_code": "从客户端代码中删除DATABASE_URL",
"verify_env_vars": "确保未使用NEXT_PUBLIC_DATABASE_URL或类似变量"
}
}Add to timeline.md (P0)
添加到timeline.md(P0级)
markdown
undefinedmarkdown
undefined[TIMESTAMP] - 🔴 P0 CRITICAL: Database Connection String Exposed
[TIMESTAMP] - 🔴 P0严重:数据库连接字符串已暴露
- PostgreSQL connection string with password found in client code
- Location: [file]:[line]
- Impact: Direct database access, full RLS bypass
- Evidence:
02-extraction/db-string-exposure/ - IMMEDIATE PASSWORD ROTATION REQUIRED
undefined- 在客户端代码中发现带密码的PostgreSQL连接字符串
- 位置:[文件]:[行号]
- 影响:直接访问数据库,完全绕过RLS
- 证据:
02-extraction/db-string-exposure/ - 需立即轮换密码
undefinedRelated Skills
相关技能
- — Check for service key exposure
supabase-extract-service-key - — Test data access via API
supabase-audit-tables-read - — Generate comprehensive report
supabase-report
- — 检查服务密钥是否暴露
supabase-extract-service-key - — 通过API测试数据访问权限
supabase-audit-tables-read - — 生成综合报告
supabase-report