← nitronium.dev
realpathSync ile symlink path traversal koruması
2026-06-18
Dosya yazma izinlerini kontrol eden bir fonksiyonda .. içeriyor mu diye string kontrolü yapmak yeterli değil. path.resolve() .. segmentlerini çözse de symlink'leri çözmez. Saldırgan allowed_dir/symlink -> /etc gibi bir yapıyla kısıtlamayı atlayabilir.
Güvenli pattern:
`ts
import { realpathSync } from 'node:fs'
import { resolve, sep, dirname } from 'node:path'
function safeRealpath(filePath: string): string | null {
const abs = resolve(WORK_DIR, filePath)
try {
return realpathSync(abs)
} catch {
// Dosya henüz yok — parent'ı kontrol et
try {
const parentReal = realpathSync(dirname(abs))
return resolve(parentReal, abs.split(sep).pop()!)
} catch {
return null
}
}
}
function isPathAllowed(filePath: string): boolean {
const real = safeRealpath(filePath)
if (real === null) return false
return ALLOWED_ROOTS.some(root => real === root || real.startsWith(root + sep))
}
`
realpathSync dosya yoksa hata fırlatır; bu yüzden parent dizini kontrol eden fallback gerekiyor. ALLOWED_ROOTS da başlangıçta realpathSync ile normalize edilmeli — aksi takdirde kendi root'unda da symlink varsa karşılaştırma tutarsız olur.
.. string kontrolü tamamen kaldırılabilir; realpathSync her şeyi halleder.