spring-projects/spring-security · error · RequestRejectedException
The was rejected because it can only contain printable…
Error message
The %s was rejected because it can only contain printable ASCII characters.
What it means
StrictHttpFirewall rejects request fields (here the requestURI) containing characters outside the printable ASCII range (32-126). Non-printable or non-ASCII characters in URLs are typical of smuggling/ injection attempts and are never legitimate in an HTTP request line, so the firewall throws RequestRejectedException naming the rejected field via String.format.
Solutions
- Percent-encode non-ASCII data before putting it in the URL path (use UriComponentsBuilder.encode() or client-side encodeURIComponent)
- URL-decode/encode consistently at the gateway so the request line contains only ASCII; reject or sanitize such requests at the proxy
- If identifiers must be human-readable text, move them into a query parameter or request body where encoding rules differ, or use opaque IDs
- Inspect access logs to identify the offending client; if it is an attacker/probe, no fix is needed — the firewall is working as intended
Example fix
// before
String url = "/users/" + username; // username may contain unicode/control chars
// after
String url = UriComponentsBuilder.fromPath("/users/{username}")
.buildAndExpand(username)
.encode().toUriString(); Defensive patterns
Strategy: validation
Validate before calling
String uri = request.getRequestURI();
boolean printableAscii = uri.chars().allMatch(c -> c >= 32 && c < 127);
if (!printableAscii) {
// percent-encode before sending, or reject at the client/gateway
} Try / catch
try {
FirewalledRequest fw = firewall.getFirewalledRequest(request);
chain.doFilter(fw, response);
} catch (RequestRejectedException e) {
log.warn("Non-printable ASCII in {}: {}", "requestURI", request.getRequestURI());
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
} Prevention
- Always percent-encode path parameters containing unicode or control characters
- Keep user-supplied free text out of URL paths — use query params, bodies, or opaque IDs
- Sanitize/validate path segments with a regex like [\x20-\x7E]+ before making outbound requests
- Treat violations in logs as probe traffic and correlate with WAF/IP blocking rules
When it happens
Trigger: getFirewalledRequest delegates to rejectNonPrintableAsciiCharactersInFieldName(request.getRequestURI(), "requestURI") and the URI contains bytes like %00, control characters, or raw UTF-8 multibyte sequences (e.g. %E4%B8%AD decoded raw in the URI).
Common situations: APIs that carry user names or search terms in the path with unencoded unicode; XSS/filter-evasion probes sending %00 or newline bytes; legacy clients sending unencoded UTF-8; log-injection tooling tests; bot traffic with obfuscated URIs.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- The requestURI cannot contain encoded slash. Got " +…
- The was rejected because it can only contain printable…
- Un-normalized paths are not supported: " +…
- 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/65791a1098ae4520.
Report an issue: GitHub.
Appendix: source
Thrown at web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java:529
this.encodedUrlBlocklist.removeAll(values);
this.decodedUrlBlocklist.removeAll(values);
}
@Override
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
rejectForbiddenHttpMethod(request);
rejectedBlocklistedUrls(request);
rejectedUntrustedHosts(request);
if (!isNormalized(request)) {
throw new RequestRejectedException("The request was rejected because the URL was not normalized.");
}
rejectNonPrintableAsciiCharactersInFieldName(request.getRequestURI(), "requestURI");
return new StrictFirewalledRequest(request);
}
private void rejectNonPrintableAsciiCharactersInFieldName(String toCheck, String propertyName) {
if (!containsOnlyPrintableAsciiCharacters(toCheck)) {
throw new RequestRejectedException(String
.format("The %s was rejected because it can only contain printable ASCII characters.", propertyName));
}
}
private void rejectForbiddenHttpMethod(HttpServletRequest request) {
if (this.allowedHttpMethods == ALLOW_ANY_HTTP_METHOD) {
return;
}
if (!this.allowedHttpMethods.contains(request.getMethod())) {
throw new RequestRejectedException(
"The request was rejected because the HTTP method \"" + request.getMethod()
+ "\" was not included within the list of allowed HTTP methods " + this.allowedHttpMethods);
}
}
private void rejectedBlocklistedUrls(HttpServletRequest request) {
for (String forbidden : this.encodedUrlBlocklist) {
if (encodedUrlContains(request, forbidden)) {View on GitHub (pinned to 96852e8860)