← nitronium.dev

CTE ismiyle SQL allowlist bypass

2026-06-06
SQL allowlist'i regex ile uyguluyorsan CTE isimleri kör noktandır.

`sql
-- Allowed tables: pages, content_chunks, links ...
-- Blocked tables: access_tokens, oauth_clients ...

-- Sıradan bypass:
WITH access_tokens AS (SELECT * FROM access_tokens)
SELECT * FROM access_tokens
`

Regex FROM access_tokens görür, access_tokens'ı CTE alias olarak tanır ve allowlist kontrolünü atlar. Oysa CTE gövdesindeki FROM access_tokens gerçek tabloya gidiyor.

Kök neden: regex hangi FROM'un CTE gövdesi içinde, hangisinin dışarıda olduğunu anlayamaz.

Hızlı fix: CTE isimlerini restricted tablo listesiyle çapraz kontrol et.

`typescript
const BLOCKED_CTE_NAMES = new Set(['access_tokens', 'oauth_clients', ...]);
for (const match of sql.matchAll(/\b(\w+)\s+as\s*\(/gi)) {
if (BLOCKED_CTE_NAMES.has(match[1])) throw new Error('CTE name shadows restricted table');
}
`

Gerçek fix: SQL parse tree kullan. node-sql-parser veya pg_query CTE body'sini ve outer query'yi ayrı node olarak verir, shadow mümkün değil.

---