The fix, in one snippet
ALLOWED = {'/dashboard', '/settings'}
target = request.args.get('next', '/')
return redirect(target if target in ALLOWED else '/')
Illustrative values. Change the paths, hostnames and options to match your own site before using it.
The sections below explain what is tested, why it matters and the alternatives.
What we test
Scan.now examines the page URL, every link and every form action on the homepage for query parameters commonly used to carry a post-action destination: redirect, redirect_uri, redirect_url, url, next, return, returnUrl, return_to, goto, dest, destination, continue, target, forward and out. It reports each occurrence where the value is an absolute URL or a path, with the endpoint it belongs to. This is an inventory, rated info: Scan.now does not send altered values to see whether the application will redirect to an external host, because that would be an active test. The finding tells you where to look; confirming the behaviour takes one manual request with an external URL in the parameter.
Why it matters
An open redirect (CWE-601) is an endpoint that sends the browser wherever a parameter says. On its own it is a low-impact bug; combined with a plausible link it is a phishing engine. The victim receives https://bank.example/login?next=https://bank-example.help/, checks the domain at the start, logs in, and is forwarded to a lookalike that asks them to "confirm" their credentials. Because the first hop is genuinely your domain, email filters and users both trust it. Redirect parameters also undermine other controls: an OAuth flow whose redirect_uri is loosely matched can leak authorisation codes, which RFC 9700 (OAuth 2.0 Security Best Current Practice) addresses at length, and allowlists elsewhere in the application that trust "any URL on our domain" are bypassed by a redirecting one. The phishing guide shows the user-side view of this trick.
How to fix it
Only ever redirect to a relative path, or to a destination chosen from a server-side allowlist, and never to a value that arrived in the request. Express:
function safeNext(value) {
if (typeof value !== 'string') return '/';
// relative path only: single leading slash, no scheme, no protocol-relative //
if (/^\/(?!\/)/.test(value) && !/[\\\r\n]/.test(value)) return value;
return '/';
}
app.post('/login', (req, res) => { /* ... */ res.redirect(safeNext(req.body.next)); });
Django ships a validator for exactly this:
from django.utils.http import url_has_allowed_host_and_scheme
if url_has_allowed_host_and_scheme(next_url, allowed_hosts={request.get_host()}, require_https=True):
return redirect(next_url)
return redirect('/')
Rails 7 raises on cross-host redirects unless you pass allow_other_host: true, so keep that default. Where you genuinely need to send users off-site (an outbound link tracker), map an opaque identifier to the URL on the server rather than accepting the URL itself. For OAuth, register exact redirect URIs and compare them with string equality, as RFC 9700 requires. After fixing, test each endpoint on the inventory with ?next=https://example.org/ and confirm it lands on your own site.
Where this fits
Redirect parameters on the page is check 12 of 14 that the website vulnerability scanner runs under exposed files and information disclosure, ordered the way they are worth fixing. That ordering is the point: Fixing this one while the check above it still fails buys less than it looks like.
Fix this one first
Above it in the same category sits WordPress version disclosure (low), where the site runs WordPress and reveals its exact core version through the generator tag, asset query strings, readme.html or the feed, letting attackers match it against known core vulnerabilities. An attacker who has that does not need this, so it is the better use of the same hour.
What fixing this still leaves open
Redirect parameters on the page closes one route in. Immediately below it: robots.txt review, where a review of robots.txt; security.txt (RFC 9116) present, where no security.txt file was found at /.well-known/security.txt, or the one present is invalid or expired.
Found in the same scan
The website vulnerability scanner reports this alongside checks from other categories that are at least as serious, including Certificate chain and hostname validation, where the certificate presented for this hostname did not validate: The chain does not reach a trusted root, an intermediate is missing, the name does not match, or the certificate is self-signed or expired, and HTTPS is available, where the site could not be reached over HTTPS on port 443, or the TLS handshake failed. A single run of website vulnerability scanner answers all of them at once.
The first few lines
You are a senior web engineer. I ran a security and SEO scanner against my site and it reported the finding below. Fix it properly rather than suppressing the symptom.
Finding: Redirect parameters on the page (info severity)
Scanner check id: open-redirect-parameters
The rest of this prompt names the pages and line numbers we found the problem on, the configuration to change, and the constraints a good answer has to respect. It is free, it just needs an account so the work is not scraped wholesale.
Sign in with GoogleSigning in is free and takes one click. We store your email address and nothing else.