Startup Cybersecurity // 2026
CybersecurityApril 19, 2026·9 min read

SSRF Vulnerabilities in Next.js and Node.js: How Startups Expose Internal Services

SSRF is what happens when your server fetches on behalf of an attacker. In cloud-native startup apps, that can mean internal dashboards, metadata credentials, local services, or any private network path you forgot the server can see.

What Makes SSRF Dangerous

SSRF turns your backend into the attacker's proxy. If a feature accepts a URL and your server fetches it without restrictions, the attacker can often reach systems their browser never could: metadata endpoints, internal APIs, loopback services, private dashboards, and sensitive integration surfaces.

Modern startup products are full of URL-powered features: OG previews, PDF imports, webhook callbacks, crawl jobs, feed ingestion, image fetchers, file scanners, and AI tools that summarize remote pages. Each one looks like a harmless convenience until someone realizes the server will fetch almost anything it is asked to fetch.

That is why SSRF keeps appearing in cloud incidents. The browser can only see the public internet. Your server can usually see much more. If you do not force an allowlist and network boundaries, you are effectively handing attackers a backend network pivot built into your product.

4
Common product features that hide SSRF risk
2
High-value targets: metadata and internal APIs
1
Safe default: allowlist, not open fetch

Why SSRF Still Works in Cloud Apps

SSRF works because the trust model is backwards. A feature says “let the server fetch this URL for the user,” but the server has access the user does not. In a cloud environment that often includes metadata endpoints, internal dashboards, private service-to-service APIs, and anything bound to loopback or RFC1918 addresses.

The startup-specific risk is that SSRF almost always hides inside a perfectly legitimate product feature. Nobody creates an “SSRF endpoint.” They create a website preview, an import-from-URL tool, a Slack unfurl, or a crawler for lead enrichment. The vulnerability is in the lack of network policy around that feature.

Redirects make it worse. Even if the initial hostname looks safe, a redirect can bounce the request somewhere private unless you explicitly block it.

Common SSRF Entry Points in Startup Products

Preview

Link preview or OG image fetchers

A user pastes a URL and the backend retrieves remote HTML or metadata. Without an allowlist, that path can hit internal services.

Imports

Import-from-URL flows

CSV, PDF, or image imports often trust a user-supplied URL and fetch directly from the server for convenience.

Webhooks

Webhook validation or retry logic

Some systems fetch callback URLs or follow redirects while attempting delivery, which can create an unexpected SSRF surface.

AI

AI tools that summarize a URL

AI features frequently accept a webpage URL, fetch the content server-side, and pass it into an LLM. That is still network access and needs hard limits.

Ops

Internal support utilities

Ops or support pages often have “fetch this URL” helpers for debugging integrations, then accidentally stay reachable in production.

Never Fetch a Raw User URL From the Server

If the server is going to make outbound requests, it needs a network policy just as much as your inbound API does.

Open Fetch Path
export async function POST(req: Request) {
  const { url } = await req.json();

  const response = await fetch(url);
  const html = await response.text();

  return Response.json({ html });
}
Allowlisted Fetch Path
const ALLOWED_HOSTS = ['docs.stripe.com', 'developer.mozilla.org'];

export async function POST(req: Request) {
  const { url } = await req.json();
  const parsed = new URL(url);

  if (parsed.protocol !== 'https:') {
    return Response.json({ error: 'Only https URLs allowed' }, { status: 400 });
  }

  if (!ALLOWED_HOSTS.includes(parsed.hostname)) {
    return Response.json({ error: 'Host not allowed' }, { status: 403 });
  }

  const response = await fetch(parsed.toString(), { redirect: 'error' });
  return Response.json({ html: await response.text() });
}

For broader products, use a resolver that blocks private IP ranges, loopback, metadata addresses, and unexpected redirects before the request leaves the server.

If a feature does not truly need arbitrary URL fetching, do not support it. Narrow the feature instead of widening the attack surface.

SSRF Defense Checklist for Startups

Allowlist domains when business logic permits it

Allowlist

The safest URL fetch feature is one that only talks to approved providers or customer-owned domains you explicitly expect.

Reject private, loopback, and metadata ranges

Network

Do not let outbound requests reach 127.0.0.1, localhost, RFC1918 ranges, or 169.254.169.254.

Block unexpected redirects

Redirects

An apparently safe public host can redirect to a private target unless the fetch layer stops it.

Time-box and size-box responses

Limits

Even benign external fetches should have strict timeouts and body-size limits so SSRF does not become a resource-drain attack.

Scan every fetch path in the repo

Automation

Search for fetch(), axios, request, and SDK helpers that can receive user-controlled URLs through params, body fields, or database values.

Map Your URL Fetch Paths

Find SSRF Risk Before It Becomes Cloud Credential Theft

Scan the repo for dangerous fetch flows and narrow every product feature that lets a caller choose where your backend connects.

// npx custodia-cli scan
$ npx custodia-cli scan

  ┌──────────────────────────────────────────────────────┐
  │  CUSTODIA.DEV  //  STARTUP SECURITY ANALYSIS         │
  └──────────────────────────────────────────────────────┘

  HIGH     INJ-05 Open URL fetch in preview API
          src/app/api/preview/route.ts:16
          User-supplied URL passed directly into fetch() with no host or network restriction.

  MEDIUM   INJ-05 Redirect-follow SSRF risk
          src/lib/importRemoteAsset.ts:33
          Fetcher follows redirects automatically and does not block private-network targets.

  MEDIUM   INJ-05 AI URL summarizer
          src/app/api/summarize-url/route.ts:20
          LLM summarization endpoint retrieves arbitrary remote content from caller-provided URLs.

  ───────────────────────────────────────────────────────
  OUTPUT: file-level findings, fix guidance, severity map
  COVERAGE: auth, secrets, injection, access control, AI
Scan My CodebaseView Demo Report

Frequently Asked Questions

What is SSRF?

SSRF stands for server-side request forgery. It happens when an attacker can influence a backend system to make a network request to a target of the attacker's choice.

Why is SSRF so dangerous in the cloud?

Because cloud workloads often have network access to internal services and metadata endpoints that contain credentials or infrastructure details browsers cannot reach directly.

Are URL preview features inherently risky?

Yes. They are not necessarily unsafe if built carefully, but they are one of the highest-frequency SSRF entry points and should never use raw open fetch behavior.

Is blocking localhost enough?

No. You also need to block private ranges, metadata IPs, alternate encodings, and redirect chains. SSRF protection is a network policy, not a string match.

Can a code scan find SSRF paths?

It can catch many high-signal cases where user-controlled values flow into fetch-like APIs without a visible allowlist or boundary check. That is a good first pass before manual review.

Related Articles
CybersecurityNext.js Security Checklist for StartupsCybersecurityAPI Rate Limiting for StartupsCybersecurityPre-Launch Security Checklist for Solo Developers