T05 · Unauthorized Access and Privilege Escalation
- Location
src/server.mjs:131- Finding
Source resolution permits SSRF through incomplete IP validation and DNS rebinding
- Content
View full analysis
Number.isNaN(x) || x < 0 || x > 255)) return true; const [a, b] = p; return ( a === 0 || a === 10 || a === 127 || (a === 169 && b === 254) || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168) || a >= 224 ); } async function assertSafeFetchUrl(rawUrl) { const u = new URL(rawUrl); if (!['http:', 'https:'].includes(u.protocol)) throw new Error('invalid url scheme'); const host = u.hostname; if (host === 'localhost' || host.endsWith('.localhost')) throw new Error('blocked host'); if (isIP(host) && isPrivateOrSpecialIp(host)) throw new Error('blocked host'); const resolved = await lookup(host, { all: true }); if (!resolved.length || resolved.some((r) => isPrivateOrSpecialIp(r.address))) { throw new Error('blocked host'); } } async function httpFetch(url, timeout = 5000, redirectsLeft = 3) { await assertSafeFetchUrl(url); return new Promise((resolve, reject) => { const mod = url.startsWith('https') ? https : http; const r = mod.get(url, { headers: { 'User-Agent': 'AI-Digest/1.0', 'Accept': 'text/html,application/xhtml+xml,application/xml,application/json,*/*' } }, async (resp) => { try { if (resp.statusCode >= 300 && resp.statusCode < 400 && resp.headers.location) { clearTimeout(timer); if (redirectsLeft <= 0) return reject(new Error('too many redirects')); const nextUrl = ...[truncated 3562 chars]- Remediation
View remediation
