Security ⚑ High severity

SSRF via URL Parser

User-supplied URL passed to fetch() without validation — attackers bypass DNS blocks via IP notation tricks.

Server-Side Request Forgery happens when a user-supplied URL is passed to `fetch()` or `http.request()` without proper validation. If the IP address is parsed incorrectly, attackers bypass DNS-based blocks using octal/hex IPv4 notation, IPv6 variants, or URL redirects. The `ip` npm package’s `isPublic()` had a bug where `127.1` (== 127.0.0.1) was classified as public.

❌ Vulnerable
// VULNERABLE — no SSRF protection
app.get('/fetch', async (req, res) => {
  const url = req.query.url;
  const response = await fetch(url); // attacker: ?url=http://127.1:8080/admin
  res.json(await response.json());
});
✓ Fixed
// FIXED — explicit allowlist + URL parsing
const ALLOWED_HOSTS = ['api.example.com', 'cdn.example.com'];
app.get('/fetch', async (req, res) => {
  const url = new URL(req.query.url);
  if (!ALLOWED_HOSTS.includes(url.hostname)) {
    return res.status(403).json({ error: 'Host not allowed' });
  }
  const response = await fetch(url.href);
  res.json(await response.json());
});
CVE-2024-29415 (ip package SSRF via isPublic() misclassifying 127.1, 01200034567, 000:0:0000::01 as public). Incomplete fix of CVE-2023-42282. The isPublic() function incorrectly allowed bypass via `x7f...1`, `0177.1`, `::fFFf:127.0.0.1`. Also CVE-2025-59436, CVE-2025-59437 (ip package SSRF via "0" IP address). CVE-2026-44578 (Next.js WebSocket SSRF, CVSS 8.6, May 2026) — absolute-form URI proxying in built-in Node.js server reaches cloud metadata.
PullLight flags URL fetch calls where the URL is derived directly from user input (`req.query`, `req.body`, `req.params`) without hostname validation or allowlist. It detects use of the `ip` package’s `isPublic()` without additional validation, and flags patterns where `fetch(url)` is called with unsanitized user input.
See it in action — paste a diff into /analyze
Try a vulnerable example: pool.query(`SELECT * FROM users WHERE id = ${req.params.id}`)
Analyze a diff →