Securing URLs: SSRF, Open Redirects, and Validation

Prevent SSRF, open redirects, and URL injection in web applications. Validate URLs correctly to block attacks using percent-encoding, IP ranges, and scheme abuse.

Securing URLs: SSRF, Open Redirects, and Validation

URLs in user-supplied input are a recurring attack vector. Server-side request forgery (SSRF) occurs when a server makes an HTTP request to a URL controlled by an attacker, potentially reaching internal services on the server's network. Open redirect vulnerabilities allow attackers to craft URLs on your domain that forward users to malicious sites. Both attacks rely on insufficient URL validation because they accept URLs that look legitimate but resolve to unintended destinations.

Defending against URL-based attacks requires validating scheme, host, and resolved IP address rather than just the surface-level string. Percent-encoding, IPv6 addressing, DNS rebinding1, and redirect chains are all used to bypass naive validation checks.

Run this check yourself in the URL Parser & Inspector.

Open in the tool →

Preventing server-side request forgery (SSRF)

SSRF occurs when user-controlled URL input reaches a server-side HTTP client. Validate that the URL's scheme is http or https, then resolve the hostname to an IP address and check that the IP is not in a private range: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, ::1, and cloud metadata IPs like 169.254.169.2541.

Why request-time validation matters more than validation-time checks

Consequently, perform the IP check at request time, not at validation time, because DNS rebinding can change what an IP resolves to between checks. Building on this, avoid following redirects automatically for user-supplied URLs; validate the Location header at each hop using the same IP-range checks. This defense-in-depth approach ensures that even if one layer is bypassed, the next layer catches the attack before any outbound request is made.

Your validation layer should treat every DNS resolution as a fresh security decision. Even if the IP was safe milliseconds ago, the next resolution could point to an internal metadata endpoint. Treat each request as a new validation event. DNS rebinding attacks exploit the gap between validation and request execution by swapping the resolved address to an internal IP after your initial check passes. Caching the validation result defeats the entire purpose of request-time IP verification because the attacker controls the TTL and can force a fresh resolution at the moment of attack.

Preventing open redirect vulnerabilities

An open redirect allows an attacker to craft a URL like https://example.com/redirect?url=https://evil.com that your server forwards users to. The fix is to validate the redirect target against an allowlist of trusted domains or to use a relative path instead of an absolute URL2. Building on this, check the parsed URL, not the raw string, because percent-encoding and Unicode lookalike characters can bypass string-level checks. Verify that the URL's hostname exactly matches an allowed domain after parsing with a standards-compliant URL library. Consequently, do not pass user input through a redirect parameter at all if you can use session state or path-based routing instead.

Encoding attacks and parser differentials

URL parsing inconsistencies between different components of your stack can create security gaps. A web application firewall may parse a URL differently than the backend application, allowing an attacker to slip through a malicious path using double-encoding (%252F for /) or unusual normalization. Consequently, normalize all URLs before validation: decode percent-encoding once, resolve dot-segments, and canonicalize the host. Spot a URL that hides its real host after @ before you trust the domain shown in a link: some URL parsers treat @ in the path as a userinfo separator, so https://[email protected]/ may parse as a URL to evil.com with safe.com as userinfo2. Always check the parsed hostname, not the raw string, because the hostname is the security boundary that determines which server the request reaches.

URL parsing differentials between application layers

A URL that passes validation in one layer of your stack may be interpreted differently in another. A web application firewall that parses URLs with a custom regex sees https://example.com%2F..%2Fadmin as a request to /admin. Your application framework, using the WHATWG URL Standard, sees it as a path containing literal %2F characters pointing to /..%2Fadmin3. This parsing differential lets attackers bypass WAF rules. Normalize all URLs at the WAF layer before comparison: decode percent-encoding once, resolve dot-segments, and then compare the canonical form against your blocklist.

URL-based denial of service via parser edge cases

Specially crafted URLs can cause excessive CPU consumption in URL parsers. A path containing thousands of dot-segments (/a/b/c/../../../../...) forces the parser to iterate through every segment during normalization. Attackers exploit this by sending URLs with thousands of nested dot-segments, causing CPU spikes on the server. Set a maximum URL length (most frameworks default to 8 KB) and a maximum number of path segments in your web server or reverse proxy configuration. Nginx's large_client_header_buffers directive controls the maximum request URI length; set it to reject URLs longer than 8 KB before they reach your application code4.

Secure URL handling in server-side rendering frameworks

Server-side rendering frameworks (Next.js, Nuxt, SvelteKit) that accept URLs from user input must sanitize before rendering into HTML. A meta tag like <meta property="og:url" content="{{ userUrl }}"> is vulnerable to XSS if userUrl contains javascript: or an unescaped ". Sanitize user-supplied URLs by parsing with new URL(), validating the protocol is http: or https:, and then HTML-escaping the serialized URL before embedding it in markup. Next.js's built-in URL handling does not automatically sanitize; you must add explicit validation in getServerSideProps or API routes.

Subresource integrity for external URL references

When your page loads scripts, stylesheets, or images from external URLs, Subresource Integrity (SRI) ensures the resource has not changed since the hash was generated. Add the integrity attribute to script and link tags: <script src="https://cdn.example.com/lib.js" integrity="sha384-abc123..." crossorigin="anonymous"></script>. The browser fetches the resource, computes its SHA-384 hash, and compares against the declared value5. A compromised CDN serving modified JavaScript will fail the integrity check and the browser will refuse to execute the script. Generate integrity hashes at build time using tools like sri-hash or webpack-subintegrity, and update them whenever the external resource changes because serving a new script with an old hash will cause the browser to block execution.

When to use this

Apply URL security checks whenever your application accepts URLs from users, configuration files, webhooks, or third-party APIs and uses them in HTTP requests, redirects, link href attributes, or server-rendered markup.

Examples

Validate a URL for outbound HTTP requests (SSRF mitigation) in Python

import socket from urllib.parse import urlparse import ipaddress PRIVATE_RANGES = [ ipaddress.ip_network("10.0.0.0/8"), ipaddress.ip_network("172.16.0.0/12"), ipaddress.ip_network("192.168.0.0/16"), ipaddress.ip_network("127.0.0.0/8"), ipaddress.ip_network("169.254.0.0/16"), ] def is_safe_url(url: str) -> bool: parsed = urlparse(url) if parsed.scheme not in ("http", "https"): return False try: ip = ipaddress.ip_address(socket.gethostbyname(parsed.hostname)) return not any(ip in r for r in PRIVATE_RANGES) except Exception: return False

Validate open redirect target in JavaScript

Before
// Wrong: string check bypassed by https://[email protected]
function safeRedirect(url) {
  if (url.includes("example.com")) window.location = url;
}
After
// Correct: parse and check the hostname
function safeRedirect(url) {
  try {
    const parsed = new URL(url);
    const ALLOWED = ["example.com", "www.example.com"];
    if (ALLOWED.includes(parsed.hostname)) window.location = url;
  } catch { /* invalid URL — reject silently */ }
}
Sources
  1. 1.

    OWASP Foundation, "Server-Side Request Forgery Prevention Cheat Sheet," cheatsheetseries.owasp.org, accessed June 2026. https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html

  2. 2.

    OWASP Foundation, "Unvalidated Redirects and Forwards," cheatsheetseries.owasp.org, accessed June 2026. https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html

  3. 3.

    WHATWG, "URL Standard," url.spec.whatwg.org, accessed June 2026. https://url.spec.whatwg.org/#concept-basic-url-parse

  4. 4.

    nginx team, "Module ngx_http_core_module — large_client_header_buffers," nginx.org, accessed June 2026. https://nginx.org/en/docs/http/ngx_http_core_module.html#large_client_header_buffers

  5. 5.

    W3C Web Application Security Working Group, "Subresource Integrity," W3C Working Draft, w3.org, March 2026. https://www.w3.org/TR/sri-2/

FAQ

Server-side request forgery (SSRF) occurs when an attacker causes your server to make an HTTP request to a URL they control. This can expose internal services, including databases, admin panels, and cloud metadata APIs, that are not reachable from the internet. CapyToolkit offers a URL Parser tool that displays the hostname, scheme, and path of any URL you enter, which is a useful first step when inspecting a suspicious URL for SSRF indicators. Attackers use SSRF to exfiltrate credentials (e.g., AWS IAM keys from 169.254.169.254), pivot to internal networks, or read files via the file:// scheme.

Percent-encoding transforms / to %2F, . to %2E, and @ to %40. A URL validator that compares raw strings may miss that https://example.com%2Fevil.com is a path containing a /, not two hosts. After parsing, the hostname is example.com and the path is /evil.com. Always validate the parsed URL object, not the raw string.

An open redirect is a URL on your domain that accepts a target URL in a query parameter and redirects the user to it without validation. Attackers use it for phishing: https://trusted.com/redirect?url=https://evil.com looks legitimate in a URL preview, but sends users to the attacker's site. Fix it by validating the target URL against an allowlist of trusted domains.

DNS rebinding is an attack where a domain initially resolves to a legitimate IP during validation but resolves to an internal IP during the actual request. The attacker controls the DNS TTL to time the switch. To mitigate, resolve the IP and check it at request time using a patched HTTP client that binds to the resolved address, preventing re-resolution.

Parse the URL, check that the scheme is http or https (blocking javascript:, data:, vbscript:), and set the href using the DOM property, not innerHTML. In React: <a href={validatedUrl}>. In plain JavaScript: anchor.href = validatedUrl (safe because the browser normalizes it) rather than anchor.setAttribute('href', rawInput). Always validate the scheme because a javascript: URL as an href executes code when clicked, and that is the most common vector for DOM-based XSS from user-supplied links.

Additional resources

Guides

Extracting Query Parameters from a URL Parse URL query strings in JavaScript, Python, Go, and PHP. Extract, read, and modify individual query parameters correctly, including encoded values and repeated keys. How to Validate URLs in Code Validate URLs in JavaScript, Python, Go, and PHP. Learn which validation approaches handle schemes, hostnames, paths, and encoded characters correctly. Parsing and Validating OAuth Redirect URIs Parse and validate OAuth 2.0 redirect URIs. Understand exact-match rules, fragment restrictions, and common implementation mistakes in authorization code flows. Designing REST API URLs: Paths, Params, and Versions Design clean, consistent REST API URLs. Best practices for path structure, query parameters, versioning, and encoding in HTTP API design. URL Canonicalization and Normalization Understand URL canonicalization: normalizing schemes, hosts, paths, and query strings to produce a single canonical form for caching, deduplication, and SEO. Resolving Relative URLs Against a Base URL Resolve relative URLs correctly in JavaScript, Python, and Go. Understand the RFC 3986 algorithm for resolving path-relative, root-relative, and protocol-relative references. Tracing Short URLs and Redirect Chains Follow URL shorteners and redirect chains programmatically. Resolve bit.ly, t.co, and custom redirects to their final destinations in JavaScript, Python, and curl. Securing URLs: SSRF, Open Redirects, and Validation Prevent SSRF, open redirects, and URL injection in web applications. Validate URLs correctly to block attacks using percent-encoding, IP ranges, and scheme abuse.