Safeguard
Application Security•

CWE-180 Validate Before Canonicalize: The Order That Breaks Checks

Checking a path or name before it is reduced to its canonical form lets tricks like fakechild/../realchild through. How CWE-180 works and the fix.

Safeguard Security Team
2 min read

CWE-180, Incorrect Behavior Order: Validate Before Canonicalize, is a specific case of early validation. The product checks input before it is canonicalized, so it cannot spot data that only becomes invalid once it is reduced to its standard form.

Canonicalization means turning the many ways of writing one thing into a single agreed form. "a/b/../c" and "a/c" name the same place. File paths, URLs, hostnames and Unicode text all have this property.

How it happens

A check written against the raw string sees the clutter, not the meaning. MITRE notes the attacker uses this to bypass validation and launch attacks that the validation would otherwise prevent, such as injection.

The vulnerable shape, in Python:

# Vulnerable
def open_doc(user_path):
    if not user_path.startswith("/srv/docs/"):
        raise PermissionError
    return open(user_path)          # "/srv/docs/../../etc/passwd" passes the check
# Fixed: canonicalize first, then check the result
import os
def open_doc(user_path):
    real = os.path.realpath(user_path)
    if not real.startswith("/srv/docs/"):
        raise PermissionError
    return open(real)

MITRE's observed examples include CVE-2000-0191, noted as overlapping the pattern "fakechild/../realchild". The raw string starts with an innocent looking name, and the real target only appears after the dot dot segment is resolved.

What an attacker gains

MITRE lists access control impact through bypass of a protection mechanism.

How to find it

The record has no detection methods. Look for validation code that reads the raw request value, then test with equivalent but differently written forms of a blocked target: extra dot segments, mixed separators, alternate encodings.

How to fix it

These are general steps, since the record lists no mitigations.

  1. Canonicalize with the platform's own function, not a hand written one.
  2. Run the check on the canonical result.
  3. Use the canonical result for the operation, not the original string.

Quick check

Why use the canonical value for the operation too? If you check the canonical form but act on the raw one, the two can still differ at the moment of use.

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.