Back to Blog
SecurityJuly 10, 20264 min read

SSRF Prevention: Secure Your Node.js Microservices

Master SSRF prevention in Node.js. Stop attackers from exploiting internal services by implementing strict allowlist URL filtering and network isolation.

SSRFNode.jsSecurityWeb SecurityMicroservicesOWASP

Stopping the SSRF Bleed

Last year, I spent about three days refactoring a microservice that was leaking internal metadata—all because of a seemingly innocent feature that allowed users to fetch remote profile images. We were just using a simple regex to check if the URL started with https://. An attacker eventually bypassed it by using an IP-based internal loopback address, and suddenly, they were probing our internal Redis cache.

SSRF prevention is rarely about one single check. It’s about assuming the input is malicious and building layers that make it impossible for your server to reach anything it doesn't strictly need to see.

Why Simple Validation Fails

Most developers start by using a blocklist. You might try to filter out 127.0.0.1, localhost, or private IP ranges like 10.0.0.0/8. Don't do this. Attackers use DNS rebinding, IPv6 equivalents (::1), or decimal-encoded IP addresses to bypass these filters.

When you're building Node.js security into your API, you need to shift from "blocking bad stuff" to "allowing only the good stuff."

The Allowlist Approach

Instead of checking what the URL isn't, check exactly what it is. Define a strict schema for your external requests.

  1. Parse the URL: Always use the built-in URL class in Node.js.
  2. Validate the Protocol: Only permit https:. Never allow file:, gopher:, or dict:.
  3. Validate the Hostname: Use an allowlist of domains. If you need to fetch from a dynamic user-provided URL, you should proxy that request through a hardened service rather than letting your core microservice handle it.
JAVASCRIPT
const { URL } = require(CE9178">'url');

const ALLOWED_HOSTS = [CE9178">'images.example.com', CE9178">'cdn.trusted.org'];

function isSafeUrl(urlString) {
  try {
    const parsed = new URL(urlString);
    
    // Only allow HTTPS
    if (parsed.protocol !== CE9178">'https:') return false;
    
    // Strict domain check
    return ALLOWED_HOSTS.includes(parsed.hostname);
  } catch (err) {
    return false;
  }
}

Network-Level Isolation

Even with perfect code, a vulnerability in a third-party library or a complex SSRF payload can slip through. This is where network isolation becomes your final line of defense. If your service doesn't need to talk to the internal metadata service (like AWS's 169.254.169.254), don't let it.

StrategyBenefitTrade-off
Allowlist FilteringPrevents SSRF at the application layer.Requires maintenance of allowed domains.
Network Egress RulesStops requests to sensitive internal IPs.More complex infra setup (VPC/Firewall).
Dedicated ProxyIsolates risk from the core service.Adds latency and infrastructure overhead.

If you're interested in hardening your infrastructure, I often recommend VPS Server Setup, Deployment & Hardening to ensure your network boundaries are configured correctly from the start.

Beyond the Basics

If your app handles dynamic redirects, you’re looking at a different beast. I've covered the dangers of Open redirection and SSRF prevention in Node.js and PHP before, and the core lesson remains: follow the redirect manually and validate every single hop against your allowlist.

Also, keep an eye on your dependencies. As noted in recent security research, finding vulnerabilities is no longer the bottleneck—it's the triage and remediation. Use automated tools to ensure you aren't running outdated versions of axios or node-fetch that might have known bypasses.

FAQ

Q: Can I just block private IP ranges? A: No. DNS rebinding allows an attacker to point a domain you trust to an internal IP after your validation check has already passed. Always use an allowlist of specific domains.

Q: Does using an agent or LLM for code generation introduce SSRF risks? A: Yes. Modern AI coding assistants can sometimes trigger endpoint security rules or inadvertently suggest insecure code patterns. Always review AI-generated network logic with a human eye, especially for handling user-provided URLs.

Q: What is the best way to handle user-provided URLs? A: If possible, don't. If you must, use a dedicated, low-privilege egress proxy that has no access to your internal network or credentials.

SSRF prevention is a constant game of cat and mouse. Start by locking down your application-level filters, but always treat the network as the final, untrusted boundary. I'm still refining my own egress proxy patterns, as the landscape of "safe" vs. "unsafe" URLs changes whenever a new cloud service or internal tool gets added to our stack.

Similar Posts