supabase-extract-db-string について
supabase-extract-db-stringは、クライアント側コードに露出したPostgreSQL接続文字列やデータベース認証情報を調べるセキュリティ監査スキルです。発見事項と証拠を監査用のコンテキストファイルに記録します。
主な機能
- 01PostgreSQL接続文字列の検出
- 02漏えいしたDB環境変数の確認
- 03個別に露出した認証情報の検出
- 04クライアントコード内のORM設定を検査
- 05発見事項と証拠の記録
活用シーン
- 01WebアプリのDB認証情報漏えいを監査
- 02本番投入前にクライアントコードを確認
- 03Supabaseデータベースへのアクセスを調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yoanbernabeu/ supabase-pentest-skills --skill supabase-extract-db-stringインストール後、Claude Code で/supabase-extract-db-stringを入力して読み込まれたか確認します。
詳細
データベース接続文字列の検出
🔴 重大:コンテキストファイルの段階的な更新が必須です
最後にまとめてではなく、作業の進行中にコンテキストファイルへ書き込む必要があります。
- 発見事項ごとに、直ちに
.sb-pentest-context.jsonに書き込んでください- 各アクションの前後に
.sb-pentest-audit.logに記録してください- スキルの完了までファイルの更新を待たないでください
- スキルがクラッシュしたり中断されたりした場合に備え、過去の発見事項はすべて保存済みでなければなりません
これは任意ではありません。段階的な書き込みを怠ることは重大なエラーです。
このスキルは、PostgreSQL データベースの接続文字列がクライアント側のコードに誤って公開されていないかを検出します。
このスキルを使用するタイミング
- あらゆるセキュリティ監査の一環として
- 本番環境にデプロイする前のコードレビュー時
- Supabase のデータベースアクセスが疑われる場合
前提条件
- 対象アプリケーションにアクセスできること
- Supabase の検出が完了していること(必要に応じて自動実行されます)
これが重大な理由
データベース接続文字列が公開されると、次のことが可能になります。
| 影響 | 説明 |
|---|---|
| 🔴 DB への直接アクセス | API を迂回し、PostgreSQL に直接接続できます |
| 🔴 すべてのデータへのアクセス | RLS を介さず、すべてのデータを読み書きできます |
| 🔴 スキーマへのアクセス | データベース構造を表示、変更できます |
| 🔴 ユーザーの列挙 | auth.users テーブルに直接アクセスできます |
これは P0(重大)に該当する検出事項であり、直ちに対処する必要があります。
接続文字列のパターン
Supabase データベース URL
postgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgres
接続文字列の構成要素
| 構成要素 | 例 | 機密度 |
|---|---|---|
| ホスト | db.abc123.supabase.co | 中 |
| ポート | 5432 | 低 |
| データベース | postgres | 低 |
| ユーザー名 | postgres | 中 |
| パスワード | [your-password] | 🔴 重大 |
プーラー接続(Supavisor)
postgresql://postgres.[project-ref]:[password]@aws-0-us-east-1.pooler.supabase.com:6543/postgres
検出パターン
1. 完全な接続文字列
// ❌ CRITICAL - Full connection string
const dbUrl = 'postgresql://postgres:[email protected]:5432/postgres'
2. 環境変数の漏洩
// ❌ Exposed in client bundle
process.env.DATABASE_URL
process.env.POSTGRES_URL
process.env.SUPABASE_DB_URL
3. 一部のみの公開
// ⚠️ Password exposed separately
const DB_PASSWORD = 'MySecretPass123'
const DB_HOST = 'db.abc123.supabase.co'
4. ORM の設定
// ❌ Database config in client code
const prisma = new PrismaClient({
datasources: {
db: {
url: 'postgresql://postgres:[email protected]:5432/postgres'
}
}
})
使用方法
基本チェック
Check for database connection strings on https://myapp.example.com
詳細スキャン
Deep scan for DB credentials on https://myapp.example.com
出力形式
接続文字列が見つからない場合(良好)
═══════════════════════════════════════════════════════════
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
═══════════════════════════════════════════════════════════
接続文字列が見つかった場合(重大)
═══════════════════════════════════════════════════════════
🔴 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
═══════════════════════════════════════════════════════════
コンテキスト出力
{
"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 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
═══════════════════════════════════════════════════════════
よくある原因
| 原因 | 解決策 |
|---|---|
| 環境変数のプレフィックスの誤り | NEXT_PUBLIC_DATABASE_URL は決して使用しないでください |
| クライアント側の SSR コード | サーバー専用コードがサーバー側にとどまるようにしてください |
| バンドラーの設定ミス | 環境変数の公開について webpack/vite の設定を確認してください |
| コピー&ペーストのミス | コミットする内容を必ず再確認してください |
アーキテクチャの指針
誤り(クライアントから DB に直接接続)
// ❌ NEVER in client code
import { Pool } from 'pg'
const pool = new Pool({
connectionString: process.env.DATABASE_URL // ❌
})
正しい方法(API または Edge Function)
// ✅ 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(サーバー側)
// 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))
})
必須:コンテキストファイルの段階的な更新
⚠️ このスキルでは、実行中に追跡ファイルを段階的に更新する必要があります。最後にまとめて更新してはいけません。
重要なルール:作業の進行中に書き込む
最後にまとめて書き込むことはしないでください。代わりに、次の手順に従ってください。
- アクションを開始する前に →
.sb-pentest-audit.logにアクションを記録します - 発見事項ごとに → 直ちに
.sb-pentest-context.jsonを更新します - 重要な手順ごとに → 完了したことを
.sb-pentest-audit.logに記録します
これにより、スキルが中断されたり、クラッシュしたり、タイムアウトした場合でも、その時点までのすべての検出事項が保持されます。
必須アクション(段階的に実施)
-
検出事項を
.sb-pentest-context.jsonに更新します。{ "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] 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 -
ファイルが存在しない場合は、書き込み前に作成します。
コンテキストファイルを更新しないことは許容されません。
必須:証拠の収集
📁 証拠ディレクトリ: .sb-pentest-evidence/02-extraction/db-string-exposure/
作成する証拠ファイル(DB 文字列が見つかった場合)
| ファイル | 内容 |
|---|---|
db-string-exposure/connection-details.json | 解析済みの接続文字列(パスワードは伏せ字) |
db-string-exposure/location.txt | ファイルパスと行番号 |
証拠の形式(P0 検出事項)
{
"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"
}
}
timeline.md への追記(P0)
## [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**
関連スキル
supabase-extract-service-key— サービスキーの露出を確認しますsupabase-audit-tables-read— API 経由でデータアクセスをテストしますsupabase-report— 包括的なレポートを生成します