supabase-extract-db-string
CRITICAL - Detect exposed PostgreSQL database connection strings in client-side code. Direct DB access is a P0 issue.
Works with
---
name: supabase-extract-db-string
description: CRITICAL - Detect exposed PostgreSQL database connection strings in client-side code. Direct DB access is a P0 issue.
license: MIT
---
# Database Connection String Detection
> π΄ **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 discovery**
> - Log to `.sb-pentest-audit.log` **BEFORE and AFTER each action**
> - **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.
## When to Use This Skill
- As part of every security audit
- When reviewing code before production
- When Supabase database access is suspected
## Prerequisites
- Target application accessible
- Supabase detection completed (auto-invokes if needed)
## 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.**
## Connection String Patterns
### Supabase Database URL
```
postgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgres
```
### Connection String Components
| Component | Example | Sensitivity |
|-----------|---------|-------------|
| Host | `db.abc123.supabase.co` | Medium |
| Port | `5432` | Low |
| Database | `postgres` | Low |
| Username | `postgres` | Medium |
| Password | `[your-password]` | π΄ Critical |
### Pooler Connection (Supavisor)
```
postgresql://postgres.[project-ref]:[password]@aws-0-us-east-1.pooler.supabase.com:6543/postgres
```
## Detection Patterns
### 1. Full Connection Strings
```javascript
// β CRITICAL - Full connection string
const dbUrl = 'postgresql://postgres:MySecretPass123@db.abc123.supabase.co:5432/postgres'
```
### 2. Environment Variable Leaks
```javascript
// β Exposed in client bundle
process.env.DATABASE_URL
process.env.POSTGRES_URL
process.env.SUPABASE_DB_URL
```
### 3. Partial Exposure
```javascript
// β οΈ Password exposed separately
const DB_PASSWORD = 'MySecretPass123'
const DB_HOST = 'db.abc123.supabase.co'
```
### 4. ORM Configuration
```javascript
// β Database config in client code
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
```
### Deep Scan
```
Deep scan for DB credentials on 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
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
### 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
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## 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"
}
}
```
## 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
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## Common Causes
| Cause | Solution |
|-------|----------|
| Wrong env prefix | Never use `NEXT_PUBLIC_DATABASE_URL` |
| 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 |
## 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 // β
})
```
### Correct (API or 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')
```
### Edge Function (Server-Side)
```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))
})
```
## 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 starting any action** β Log the action to `.sb-pentest-audit.log`
2. **After each discovery** β Immediately update `.sb-pentest-context.json`
3. **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.
### Required Actions (Progressive)
1. **Update `.sb-pentest-context.json`** with findings:
```json
{
"supabase": {
"db_string_exposed": true/false,
"db_host": "db.[ref].supabase.co"
},
"findings": [
{
"id": "DB_CONNECTION_STRING_EXPOSED",
"severity": "P0",
...
}
]
}
```
2. **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
```
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/02-extraction/db-string-exposure/`
### Evidence Files to Create (if DB string found)
| File | Content |
|------|---------|
| `db-string-exposure/connection-details.json` | Parsed connection string (password redacted) |
| `db-string-exposure/location.txt` | File path and line number |
### Evidence Format (P0 Finding)
```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"
}
}
```
### Add to timeline.md (P0)
```markdown
## [TIMESTAMP] - π΄ P0 CRITICAL: Database Connection String Exposed
- 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**
```
## Related Skills
- `supabase-extract-service-key` β Check for service key exposure
- `supabase-audit-tables-read` β Test data access via API
- `supabase-report` β Generate comprehensive reportMore Database skills
supabase-postgres-best-practices
supabase/agent-skills
Postgres best practices maintained by Supabase, for Postgres running anywhere. Load this skill BEFORE writing or changing anything that lives in a Postgres database: creating or altering tables and columns (including choosing column types), schema design, migrations and declarative schema files, RLS policies and the tests that verify them, indexes, triggers, database functions, queues and scheduled jobs (pg_cron, pgmq), vector/semantic search (pgvector), and restoring dumps (pg_restore) or importing data. Also load it when diagnosing slow queries, high CPU, timeouts, EXPLAIN plans, connection exhaustion, locking, bloat, or rows visible to the wrong user or tenant. This is not just a performance guide β schema, migration, security, and SQL authoring tasks need these rules too, even for a one-column change or a single query.
prisma-database-setup
prisma/skills
Guides for configuring Prisma with different database providers (PostgreSQL, MySQL, SQLite, MongoDB, etc.). Use when setting up a new project, changing databases, or troubleshooting connection issues. Triggers on "configure postgres", "connect to mysql", "setup mongodb", "sqlite setup".
prisma-postgres
prisma/skills
Prisma Postgres setup and operations guidance across Console, create-db CLI, Management API, and Management API SDK. Use when creating Prisma Postgres databases, working in Prisma Console, provisioning with create-db/create-pg/create-postgres, or integrating programmatic provisioning with service tokens or OAuth.

