URL encoder/decoder · Guide
URL Encoding Abuse: Attack Attempts and How to Stop Them
URL encoding attacks exploit one thing: two components disagree about what a URL means. A filter reads the raw string, the application reads the decoded one, and anything they interpret differently is an opening.
Double encoding
A filter blocking ../ sees %252e%252e%252f and finds nothing suspicious. The web server decodes once to %2e%2e%2f, the application decodes again to ../, and the traversal succeeds.
The root cause is decoding more than once. Decode exactly once, at a single well-defined boundary, then validate. If a value still contains % escapes after decoding, that is a signal worth rejecting rather than helpfully decoding again.
Alternate representations
The same character has many encodings, and filters that match strings miss most of them:
../ plain
%2e%2e%2f percent-encoded
%252e%252e double-encoded
..%c0%af overlong UTF-8 (invalid, historically accepted)
..%5c backslash, normalised to / by browsersOverlong UTF-8 encodes an ASCII character in more bytes than needed. It is invalid by specification, and decoders that accept it anyway have caused real vulnerabilities — the IIS Unicode traversal being the classic case.
Where it bites in modern apps
Open redirects: a validator checking startsWith("/") accepts /%09/evil.com or /\evil.com, both of which browsers resolve off-site.
Path traversal in file-serving endpoints, SSRF filters that block localhost but not %6c%6fcalhost, and cache poisoning where a proxy and an origin normalise a URL differently.
Defending properly
Validate after decoding, never before, and decode exactly once. Compare against an allowlist of permitted values rather than a denylist of dangerous patterns — you cannot enumerate every encoding, but you can enumerate what is allowed.
For redirects and any URL you act on, parse rather than string-match:
const target = new URL(input, location.origin);
if (target.origin !== location.origin) reject();For file paths, resolve to an absolute path and confirm it is still inside the intended directory. A WAF is a useful extra layer and never the primary control — its job is pattern matching, which is exactly what these attacks defeat.
Frequently asked questions
What is a double encoding attack?
Encoding a payload twice so a filter sees harmless text while a component that decodes again sees the real payload.
Should I decode input repeatedly until it stops changing?
No. That is the vulnerability. Decode once and reject values that still contain escapes.
Is a WAF enough protection?
No. WAFs match patterns and encoding attacks exist to defeat pattern matching. Validate in the application after decoding.
Ready to try it?
Open the free browser-based URL encoder/decoder and apply what you just read — no sign-up, runs locally.
Open the URL encoder/decoder tool