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

  1. Percent-encode non-ASCII data before putting it in the URL path (use UriComponentsBuilder.encode() or client-side encodeURIComponent)
  2. URL-decode/encode consistently at the gateway so the request line contains only ASCII; reject or sanitize such requests at the proxy
  3. If identifiers must be human-readable text, move them into a query parameter or request body where encoding rules differ, or use opaque IDs
  4. 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

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


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)