Server fetches a URL the caller controls

An outbound HTTP request is made to a URL that came from the caller. The server can reach hosts the caller cannot - cloud metadata endpoints, internal admin services, databases bound to localhost - so this turns the server into a proxy into its own network. Validate the destination against an allowlist before fetching it.

high likely application source OWASP A10:2021 / CWE-918

What it looks like

HIGH likely Server fetches a URL the caller controls A10:2021 app/api/proxy/route.ts:19:28 17 │ // ssrf 18 │ if (target) { 19 │ const upstream = await fetch(target) │ ~~~~~~~~~~~~~ destination chosen by the caller 20 │ return NextResponse.json(await upstream.json()) 21 │ }

From app/api/proxy/route.ts in the fixture suite. The fixture test asserts this finding.

How to fix it

Check the destination against an allowlist of hosts before fetching it. Blocklists do not work here: DNS rebinding, redirects, and IPv6-mapped addresses all defeat them.

// lib/safe-fetch.ts
const ALLOWED_HOSTS = new Set(['api.partner.com', 'cdn.example.com'])

export function assertAllowedUrl(raw: string): URL {
  const url = new URL(raw)
  if (url.protocol !== 'https:') throw new Error('only https is allowed')
  if (!ALLOWED_HOSTS.has(url.hostname)) throw new Error('host not allowed')
  return url
}

The fix for your framework

Choose the API used by your project.

Check your own repository

npx owlwarden scan --preset deep
npx owlwarden explain ssrf

explain prints the rule and fixes in the terminal. It does not use the network.

All 25 rules / owlwarden