← nitronium.dev

MCP server'da NL→SQL expose ederken güvenlik kontrol listesi

2026-06-06
Kullanıcıya (veya AI agent'a) doğal dil sorusu yazıp SQL döndüren bir tool açıyorsan:

1. localOnly: true flag'i koy

HTTP üzerinden OAuth token'la erişilebilen bir endpoint olmamalı. Tool sadece local MCP (stdio) üzerinden çağrılabilir olsun.

2. SELECT/WITH dışını blokla

`typescript
if (!/^\s*(with|select)\b/i.test(sql)) throw new Error('Only SELECT/WITH allowed');
`

3. Tablo allowlist — ama dikkatli

Regex allowlist yeterli değil (CTE shadow bypass mümkün). Minimum: CTE isimlerini restricted tablolarla çapraz kontrol et. İdeal: SQL parse tree.

4. Tehlikeli fonksiyonları blokla

`typescript
const BLOCKED = /\b(pg_sleep|current_setting|set_config|pg_read_file|
pg_cancel_backend|pg_terminate_backend|dblink|lo_import)\b/i;
`

pg_sleep timing-based exfiltration için kullanılır. current_setting GUC parametrelerindeki secret'ları okur.

5. Statement timeout

`typescript
await engine.executeRaw("SET statement_timeout = '500ms'", []);
try { rows = await engine.executeRaw(sql, []); }
finally { await engine.executeRaw('RESET statement_timeout', []).catch(() => {}); }
`

pg_sleep regex'ten kaçarsa bile 500ms'de timeout olur.

6. Defense-in-depth: read-only DB role

Kod katmanı bypass edilse bile DB katmanı engeller:

`sql
CREATE ROLE query_role NOLOGIN;
GRANT SELECT ON pages, content_chunks, links TO query_role;
-- access_tokens, oauth_clients: intentionally dışarıda
`

LLM-generated SQL exposed etmek istiyorsan bu kontrollerin hepsi gerekli. Herhangi biri tek başına yetmez.

---