{"record":{"id":"f7e0f7c074283f59","repo":"spring-projects/spring-security","slug":"the-request-was-rejected-because-the-url-was-not-n","errorCode":null,"errorMessage":"The request was rejected because the URL was not normalized.","messagePattern":"The request was rejected because the URL was not normalized\\.","errorType":"exception","errorClass":"RequestRejectedException","httpStatus":400,"severity":"error","filePath":"web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java","lineNumber":521,"sourceCode":"\t}\n\n\tprivate void urlBlocklistsAddAll(Collection<String> values) {\n\t\tthis.encodedUrlBlocklist.addAll(values);\n\t\tthis.decodedUrlBlocklist.addAll(values);\n\t}\n\n\tprivate void urlBlocklistsRemoveAll(Collection<String> values) {\n\t\tthis.encodedUrlBlocklist.removeAll(values);\n\t\tthis.decodedUrlBlocklist.removeAll(values);\n\t}\n\n\t@Override\n\tpublic FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {\n\t\trejectForbiddenHttpMethod(request);\n\t\trejectedBlocklistedUrls(request);\n\t\trejectedUntrustedHosts(request);\n\t\tif (!isNormalized(request)) {\n\t\t\tthrow new RequestRejectedException(\"The request was rejected because the URL was not normalized.\");\n\t\t}\n\t\trejectNonPrintableAsciiCharactersInFieldName(request.getRequestURI(), \"requestURI\");\n\t\treturn new StrictFirewalledRequest(request);\n\t}\n\n\tprivate void rejectNonPrintableAsciiCharactersInFieldName(String toCheck, String propertyName) {\n\t\tif (!containsOnlyPrintableAsciiCharacters(toCheck)) {\n\t\t\tthrow new RequestRejectedException(String\n\t\t\t\t.format(\"The %s was rejected because it can only contain printable ASCII characters.\", propertyName));\n\t\t}\n\t}\n\n\tprivate void rejectForbiddenHttpMethod(HttpServletRequest request) {\n\t\tif (this.allowedHttpMethods == ALLOW_ANY_HTTP_METHOD) {\n\t\t\treturn;\n\t\t}\n\t\tif (!this.allowedHttpMethods.contains(request.getMethod())) {\n\t\t\tthrow new RequestRejectedException(","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java#L503-L539","documentation":"StrictHttpFirewall rejects any request whose URL is not normalized: it checks the requestURI/contextPath/servletPath/pathInfo for dot-segments ('/./', '/../'), duplicate slashes, and other non-canonical forms. This is a deliberate hardening against path-traversal and authorization-bypass attacks; the request is rejected with RequestRejectedException before filtering.","triggerScenarios":"getFirewalledRequest sees a URI like '/a/../b', '/a/./b', '/a//b', or containing encoded dot variants; also fired when trailing '..' or '.' segments survive. Any request through FilterChainProxy with such a path is rejected.","commonSituations":"Crawlers or misbehaving clients sending dot-segment URLs; double-encoding by proxies turning %2e%2e into '..'; apps behind proxies that don't normalize; legitimate deep links with '//' from string-concatenated base URLs; frameworks generating '/foo/./bar' links.","solutions":["Fix the URL at the source: normalize/rewrite at your reverse proxy (nginx: merge_slashes on; reject '..' patterns) or in the client/router","Find the client producing un-normalized URLs from access logs and fix its URL construction (proper path joining instead of string concatenation)","If a specific pattern is safe and required, use StrictHttpFirewall's configuration instead of reverting to DefaultHttpFirewall: e.g. setAllowUrlEncodedDoubleSlash/setAllowUrlEncodedPercent — note there is no option to allow dot-segments, so those must be normalized upstream","Wrap with a custom firewall/filter that normalizes the request (HttpFirewall wrapper or Spring Cloud Gateway rewrite filter) before it hits StrictHttpFirewall"],"exampleFix":"// before\nString url = baseUrl + \"/\" + path; // path may start with '/' or contain './'\n// after\nString url = UriComponentsBuilder.fromHttpUrl(baseUrl)\n    .path(path)\n    .build().normalize().toUriString();","handlingStrategy":"try-catch","validationCode":"String uri = request.getRequestURI();\nboolean normalized = uri.equals(URI.create(uri).normalize().getPath()) && !uri.contains(\"//\");","typeGuard":null,"tryCatchPattern":"try {\n    FirewalledRequest fw = strictFirewall.getFirewalledRequest(request);\n    chain.doFilter(fw, response);\n} catch (RequestRejectedException e) {\n    audit.log(\"Rejected non-normalized URL\", request.getRequestURI(), e.getMessage());\n    response.sendError(HttpServletResponse.SC_BAD_REQUEST);\n}","preventionTips":["Normalize all URLs at the edge (gateway/proxy rewrite rules) before they reach the app","Use URI builders that call normalize() instead of string concatenation","Set up alerting on RequestRejectedException to detect scanning traffic vs. broken clients","Write smoke tests covering dot-segment and double-slash URLs through your full proxy chain"],"tags":["spring-security","firewall","url-normalization","strict-http-firewall","security"],"backgroundTag":"path-traversal-blocked","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}