How to Fix an Open Redirect Vulnerability

An open redirect vulnerability means your /redirect endpoint will forward users to any URL an attacker supplies - making your domain the launch pad for phishing. The fix is a two-part check: the target must start with / AND must not start with //.

Security Engineerjavascriptnodejsexpress

What makes a redirect endpoint vulnerable

A typical post-login redirect looks like this:

app.get('/redirect', (req, res) => {
  const target = req.query.url;
  res.redirect(target);  // no validation
});

An attacker sends /redirect?url=https://evil.com in a phishing email. The link domain is yours, so spam filters and users trust it - but the browser lands on the attacker's site.

The two-part validation rule

A safe relative path starts with / (e.g. /dashboard) and is not protocol-relative (e.g. //evil.com). Protocol-relative URLs start with // and are treated as external by browsers, so startsWith('/') alone is not enough.

app.get('/redirect', (req, res) => {
  const target = req.query.url;

  // Must start with "/" and must NOT start with "//"
  if (
    typeof target === 'string' &&
    target.startsWith('/') &&
    !target.startsWith('//')
  ) {
    return res.redirect(302, target);
  }

  // Reject - fall back to a safe default
  res.redirect(302, '/');
});

The same pattern applies to vanilla Node.js http without Express:

function isSafeRedirect(target) {
  return (
    typeof target === 'string' &&
    target.startsWith('/') &&
    !target.startsWith('//')
  );
}

// inside your request handler:
const target = url.searchParams.get('url');
const location = isSafeRedirect(target) ? target : '/';
res.writeHead(302, { Location: location });
res.end();

Why blocklisting external URLs does not work

A common but flawed approach is checking whether the URL contains your own domain. Substring matching is easy to bypass:

Allowlisting the shape (relative path only) is the reliable approach. If you genuinely need cross-domain redirects, use a hardcoded allowlist of exact destination URLs validated through a proper URL parser - never string contains or startsWith on the hostname.

Test your fix

# Should redirect to /dashboard (302)
curl -i "http://localhost:3000/redirect?url=/dashboard"

# Should NOT redirect to evil.com - expect redirect to / or a 400
curl -i "http://localhost:3000/redirect?url=https://evil.com"

# Protocol-relative bypass - should also be rejected
curl -i "http://localhost:3000/redirect?url=//evil.com"

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

What is an open redirect vulnerability?

An open redirect is when a redirect endpoint accepts any URL from user input without validation. Attackers craft links on your domain (e.g. yoursite.com/redirect?url=https://evil.com) that look legitimate but send users to a malicious site.

Why is checking startsWith('/') not enough to fix an open redirect?

Protocol-relative URLs like //evil.com start with / but browsers treat them as external URLs pointing to evil.com. You must also reject anything starting with //. The safe rule is: starts with / AND does not start with //.

How do I fix an open redirect in Node.js or Express?

Validate the redirect target before using it: only allow strings that start with / and do not start with //. Anything else - an absolute URL, a protocol-relative URL, or a non-string - should fall back to a safe default like /.

Keep learning

Close a SQL Injection in a Search EndpointSecurity projectNeutralize a Stored XSS in CommentsSecurity projectRemove Hardcoded Credentials From Source CodeSecurity projectSecurity roadmapStep by step to hiredSecurity interview questionsSTAR answersAll Security projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →