Safeguard
Application Security•

CWE-177 Improper Handling of URL Encoding: How to Fix It

Hex encoded input such as %2e%2e can hide path traversal from a filter. How CWE-177 works and how to decode once, then validate.

Safeguard Security Team
2 min read

CWE-177, Improper Handling of URL Encoding (Hex Encoding), covers products that mishandle input that is all or partly URL encoded. Any service that takes paths, parameters or filenames from a URL is exposed.

How it happens

URL encoding writes a byte as a percent sign and two hex digits. A dot is %2e, a forward slash is %2f, a backslash is %5c. A filter that looks for the literal text ".." will miss "%2e%2e". If the application decodes the value after the filter ran, the traversal sequence reappears.

MITRE's examples for this weakness include hex encoded traversal variants such as "%2e%2e", "%2e%2e%2f" and "%5c%2e%2e", seen in CVE-2000-0900, CVE-2005-2256 and CVE-2004-2121. Another, CVE-2004-0280, involved an encoded space ("%20").

A small illustration of the vulnerable ordering, in Python:

# Vulnerable: check first, decode later
def read_file(raw_name):
    if ".." in raw_name:
        raise ValueError("bad name")
    name = urllib.parse.unquote(raw_name)   # "%2e%2e/secret" becomes "../secret"
    return open(BASE + name).read()
# Fixed: decode once, then validate the final path
def read_file(raw_name):
    name = urllib.parse.unquote(raw_name)
    path = os.path.realpath(os.path.join(BASE, name))
    if not path.startswith(os.path.realpath(BASE) + os.sep):
        raise ValueError("bad name")
    return open(path).read()

What an attacker gains

MITRE's listed consequence is integrity, an unexpected state. In practice the examples point to access to files outside the intended directory.

How to find it

Request a known blocked resource with its characters hex encoded, then double encoded, and compare against the plain request. Code review should look for any place where a check runs before a decode step.

How to fix it

The record lists no mitigations, so this is general guidance.

  1. Decode exactly once, at the edge.
  2. Validate the decoded value against an allowlist or resolve it to a real path and confirm it stays inside the allowed directory.
  3. Do not decode again further down.

Quick check

Why decode before validating? Validation must see the value the rest of the program will use. If decoding happens afterward, the check inspected something different.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.