spring-projects/spring-security · error · RequestRejectedException
Un-normalized paths are not supported: " +…
Error message
Un-normalized paths are not supported: " + firewalledRequest.getServletPath() + pathInfo
What it means
DefaultHttpFirewall rejects requests whose servletPath or pathInfo is not normalized (contain '.', '..', double slashes, or encoded variants like %2e). This is a canonicalization defense: application servers may normalize such paths differently than Spring Security, enabling path-traversal or authorization bypass. It throws RequestRejectedException before the request reaches the filter chain.
Solutions
- Normalize the URL at the proxy/gateway or client before it reaches the app (resolve dot segments, collapse duplicate slashes, reject encoded dots)
- If your container/servlet version supports it, upgrade Tomcat/Jetty so the request is rejected or normalized upstream; DefaultHttpFirewall is a fallback, prefer StrictHttpFirewall with a compatibility layer
- Temporarily relax by switching to DefaultHttpFirewall's allowUrlEncodedSlash only if that is the specific blocker — note it does NOT allow un-normalized dot paths; do not replace the firewall with a permissive one as a workaround
- Rewrite requests in a servlet filter or at the load balancer (e.g. nginx: merge_slashes, proxy_pass with normalized URI) so paths are canonical
Example fix
# nginx before
proxy_pass http://app$uri; # may forward /a/../b or //a
# after (normalize in nginx)
merge_slashes on;
# and reject dot segments:
if ($request_uri ~* \.\./) { return 400; }
proxy_pass http://app$normalized_uri; Defensive patterns
Strategy: try-catch
Validate before calling
String sp = request.getServletPath(), pi = request.getPathInfo();
String full = (sp == null ? "" : sp) + (pi == null ? "" : pi);
boolean normalized = !full.contains("/../") && !full.contains("/./") && !full.contains("//"); Try / catch
try {
FirewalledRequest fw = firewall.getFirewalledRequest(request);
chain.doFilter(fw, response);
} catch (RequestRejectedException e) {
log.warn("Rejected un-normalized path: {}", request.getRequestURI());
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
} Prevention
- Normalize URLs at the reverse proxy before forwarding (merge slashes, reject dot segments)
- Never build client URLs by raw string concatenation; use a URL builder with normalize()
- Add integration tests for paths with '/../', '/./', and '//' through your proxy stack
- Keep Spring Security and the servlet container versions aligned; upgrade containers rather than weakening the firewall
When it happens
Trigger: A request arrives where getServletPath() or getPathInfo() contains un-normalized segments: '/foo/../bar', '/foo//bar', '/%2e%2e/', or path parameters after semicolons depending on container parsing. Called via FirewallFilter/FilterChainProxy's getFirewalledRequest.
Common situations: Proxies/CDNs forwarding double-encoded URLs (%252e); clients sending dot-segment paths; servlet containers that don't strip ';jsessionid' or trailing segments; reverse proxies not normalizing before forwarding; apps mounted behind Apache with mod_proxy passing encoded slashes.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- The request was rejected because the URL was not normalized.
- The requestURI cannot contain encoded slash. Got " +…
- The was rejected because it can only contain printable…
- The request was rejected because the domain
- The request was rejected because the header name
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/13308d3ec7c40da8.
Report an issue: GitHub.
Appendix: source
Thrown at web/src/main/java/org/springframework/security/web/firewall/DefaultHttpFirewall.java:55
* valid paths which contain semi-colons.
* <p>
* If any un-normalized paths are found (containing directory-traversal character
* sequences), the request will be rejected immediately. Most containers normalize the
* paths before performing the servlet-mapping, but again this is not guaranteed by the
* servlet spec.
*
* @author Luke Taylor
* @see StrictHttpFirewall
*/
public class DefaultHttpFirewall implements HttpFirewall {
private boolean allowUrlEncodedSlash;
@Override
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
FirewalledRequest firewalledRequest = new RequestWrapper(request);
if (!isNormalized(firewalledRequest.getServletPath()) || !isNormalized(firewalledRequest.getPathInfo())) {
throw new RequestRejectedException(
"Un-normalized paths are not supported: " + firewalledRequest.getServletPath()
+ ((firewalledRequest.getPathInfo() != null) ? firewalledRequest.getPathInfo() : ""));
}
String requestURI = firewalledRequest.getRequestURI();
if (containsInvalidUrlEncodedSlash(requestURI)) {
throw new RequestRejectedException("The requestURI cannot contain encoded slash. Got " + requestURI);
}
return firewalledRequest;
}
@Override
public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
return new FirewalledResponse(response);
}
/**
* <p>
* Sets if the application should allow a URL encoded slash character.View on GitHub (pinned to 96852e8860)