T09 · Insecure Skill Coding Practices
- Location
scripts/_lnurl.js:49- Finding
Hostname-based SSRF protection does not validate resolved IP addresses
- Content
View full analysis
= 16 && b <= 31) return true; if (a === 192 && b === 168) return true; if (a === 169 && b === 254) return true; if (a === 100 && b >= 64 && b <= 127) return true; return false; } if (host === '::' || host === '::1') return true; if (/^f[cd][0-9a-f]{2}:/.test(host)) return true; if (/^fe[89ab][0-9a-f]:/.test(host)) return true; const mappedHex = host.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/); if (mappedHex) { const hi = parseInt(mappedHex[1], 16); const lo = parseInt(mappedHex[2], 16); return isPrivateAddress([hi >> 8, hi & 0xff, lo >> 8, lo & 0xff].join('.')); } if (/^::ffff:/.test(host)) return isPrivateAddress(host.replace(/^::ffff:/, '')); return false; } ``` ```js if (isPrivateAddress(host) && !explicitlyAllowed) { throw policyError(`Refusing to fetch ${what} from private address '${host}'.`); } if (opts.strictLocal && LOCAL_HOSTS.has(host) && !explicitlyAllowed) { throw policyError(`Refusing to fetch ${what} from local host '${host}' (not allowlisted).`); } ``` ```js let current = assertAllowedUrl(url, allowedHosts, what, { portsUnrestricted, strictLocal, }); res = await fetch(current.toString(), { method: reqMethod, body: reqBody, signal: controller.signal, redirect: 'manual', headers: { ...[truncated 3184 chars]- Remediation
View remediation
