CME-921

URL Request Path Canonicalization Before Authorization

Description

Ensure the web server, reverse proxy, or application framework canonicalizes request URIs — resolving path equivalences (., ..), stripping matrix parameters (;param=value), normalizing percent-encoding, collapsing duplicate slashes, and standardizing trailing slashes — before the authorization module evaluates access control rules. The root cause of CWE-551 is a behavior ordering defect where authorization sees a raw URI form that does not match configured security constraints, but the routing/dispatch layer later normalizes the URI and matches a protected resource. Canonicalization-first ensures the authorization decision and the routing decision operate on the same resolved path. Implementation varies by stack: Spring Security's StrictHttpFirewall rejects non-normalized requests; Tomcat's encodedSolidusHandling and allowBackslash settings control normalization; Nginx's merge_slashes and location matching normalize by default; Apache's AllowEncodedSlashes and mod_rewrite handle encoding normalization. Reverse proxies should be configured to normalize before forwarding to backends, and frameworks should reject requests containing path-equivalent sequences rather than silently normalizing them.

CVSS Vector Impacts

Metric Transition Rationale
Attack Complexity (AC) L H Attacker can no longer bypass authorization using non-canonical URL forms (matrix parameters, double encoding, path segment equivalences, trailing characters); exploitation requires finding a bypass that survives full URI canonicalization before the authorization decision evaluates the request

CWE Relationships

Verification

Test that non-canonical URL forms (matrix parameters, dot-segments, encoded path separators) do not bypass authorization on protected endpoints; inspect web server and framework configuration for canonicalization-before-auth settings

$ curl -s -o /dev/null -w '%{http_code}' 'http://<target>/admin/;anything'
# Expected: 401 or 403 — matrix parameter does not bypass auth
Platform: any
$ curl -s -o /dev/null -w '%{http_code}' 'http://<target>/./admin/'
# Expected: 401 or 403 — dot-segment does not bypass auth
Platform: any
$ curl -s -o /dev/null -w '%{http_code}' 'http://<target>/%2e/admin/'
# Expected: 401 or 403 — encoded dot does not bypass auth
Platform: any
$ grep -rn 'StrictHttpFirewall\|setAllowSemicolon\|setAllowUrlEncodedPercent\|setAllowUrlEncodedSlash' <app_source>/
# Expected: StrictHttpFirewall configured with restrictive defaults
Platform: any
$ grep -E 'merge_slashes|proxy_pass.*\$uri' /etc/nginx/nginx.conf /etc/nginx/conf.d/*.conf 2>/dev/null
# Expected: merge_slashes on (default); proxy_pass uses normalized $uri
Platform: linux
$ grep -i 'AllowEncodedSlashes|AllowEncodedPercent' /etc/httpd/conf/*.conf /etc/apache2/*.conf 2>/dev/null
# Expected: AllowEncodedSlashes NoDecode or absent (default deny)
Platform: linux
← CME-920: Database Least-Privilege Access Control CME-923: Mass-Assignment Prevention Through Explicit Request Schemas →