Safeguard
Application Security•

ASVS 5.0 V15.3.2: Do Not Follow Redirects in Server Calls

ASVS V15.3.2 asks that backend HTTP clients refuse redirects unless intended. This blocks a common SSRF bypass. Config for Python, Node and Java, plus tests.

Safeguard Security Team
3 min read

ASVS 5.0 V15.3.2 says that when the backend calls external URLs, the client must not follow redirects unless that is intended functionality. It is Level 2. Turn automatic redirect following off by default, and when you do need it, follow redirects manually and revalidate each target.

Why it matters

Server side request forgery defenses often check the URL a user submits: is the host allowed, does it resolve to a public address. A redirect defeats that. The attacker supplies a URL on a server they control that passes the check, then replies with a redirect to an internal address such as the cloud metadata service. If your HTTP client follows it silently, the check was pointless.

Redirects also leak. Following one can send credentials or tokens to an unexpected host, depending on the client.

How to implement it

Disable redirects at the client.

import requests
r = requests.get(url, allow_redirects=False, timeout=5)
const res = await fetch(url, { redirect: "manual", signal: AbortSignal.timeout(5000) });
if (res.status >= 300 && res.status < 400) {
  throw new Error("Unexpected redirect");
}
HttpClient client = HttpClient.newBuilder()
    .followRedirects(HttpClient.Redirect.NEVER)
    .connectTimeout(Duration.ofSeconds(5))
    .build();

If a redirect is a real requirement, such as fetching a link preview, handle it yourself: cap the hop count at three, resolve the new host, check it against the same allowlist and private range block, then request again. Apply the check to the resolved IP at connection time to avoid DNS rebinding.

Click through it at your own pace, or open it full screen.

How to test it

  1. Find every place the server fetches a user influenced URL: webhooks, imports, avatars, link previews, PDF renderers.
  2. Run a test server that answers with a 302 pointing to a local address, and submit its URL to each feature.
  3. Expect the backend to report an error and never contact the second address. Confirm in the test server and internal logs.
  4. Grep the codebase for client defaults. Many libraries follow redirects unless told otherwise.
  5. Repeat for 301, 303, 307 and 308.

Common mistakes

  • Validating the first URL and trusting the final one.
  • Setting redirect limits but not target checks.
  • Disabling redirects in one HTTP client while a second library elsewhere still follows them.
  • Forgetting server side browsers and document converters, which follow redirects on their own.

Quick check

Is a hop limit of 5 a valid control?

Only with per hop validation. A limit alone does not stop the first hop landing on an internal address.

Which level is this?

Level 2.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.