Validate every redirect destination against a server-side allowlist so a user-controlled target cannot bounce victims onto an attacker's site. Use when an endpoint reads a next, return_to, or callback parameter and sends the browser there.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add Amey-Thakur/AI-SKILLS --skill open-redirect-defense --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Open Redirect Defense?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/amey-thakur-open-redirect-defense)More formats (shields.io, HTML) on the badges page.
---
name: open-redirect-defense
description: Validate every redirect destination against a server-side allowlist so a user-controlled target cannot bounce victims onto an attacker's site. Use when an endpoint reads a next, return_to, or callback parameter and sends the browser there.
---
# Open redirect defense
A redirect that trusts its `?next=` value lets an attacker forge a link on
your trusted domain that lands the victim on theirs. It fuels phishing that
survives a careful glance at the hostname, and in OAuth flows it delivers
authorization codes to the wrong party. The fix is not smarter parsing: it is
declining any destination you did not approve in advance.
## Method
1. **Prefer a redirect map to accepting URLs at all.** Where you can, carry a
short key (`?next=inbox`) and resolve it against a server-side table of
allowed paths. A parameter that never holds a URL cannot hold a hostile one.
2. **If you must accept a URL, allowlist the host after parsing.** Parse the
target with a real URL parser, then confirm the host matches an explicit
list of your domains by exact comparison. Never judge with `startsWith` or a
substring: `https://yoursite.com.evil.com` and
`https://evil.com/?u=yoursite.com` both beat prefix checks.
3. **Default to relative paths only.** When the feature only moves within your
app, accept a target that begins with a single `/` and reject the rest.
Block `//evil.com` and `/\evil.com`, which browsers read as
protocol-relative jumps to another origin.
4. **Reject dangerous schemes outright.** Permit only `http` and `https`.
Refuse `javascript:`, `data:`, and `mailto:`, which turn a redirect into
script execution or a different trap entirely.
5. **Normalize before comparing.** Decode percent-encoding, fold backslashes to
forward slashes, strip whitespace and control characters, and lowercase the
host once, so `%2F%2Fevil.com` and mixed-case tricks cannot slip past a
check that ran against the raw string.
6. **Pin OAuth and SSO callbacks to exact registered URIs.** Match the full
callback URI against the pre-registered set with no wildcard on host or
path. A loose callback allowlist is precisely how authorization codes get
stolen.
## Checks
- Does `?next=https://evil.com` land on your domain or an error, never on
evil.com?
- Are `//evil.com` and `/\evil.com` treated as external and refused?
- Is the host matched by exact allowlist entry, not `startsWith` or `includes`?
- Are OAuth callback URIs matched exactly, with no wildcard host or path?
## Boundaries
This governs where a redirect may send the browser, nothing else. It does not
authenticate the user or protect the session that outlives the hop (see
oauth-flows for callback trust). A domain you control that also hosts user
content can still be an unsafe target: allowlisting the host is necessary, not
always sufficient.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!