spring-projects/spring-security · error · ServerExchangeRejectedException
The request was rejected because the header
Error message
The request was rejected because the header: "<key> " has a value "<value>" that is not allowed.
What it means
The firewall validates each header's value against the allowedHeaderValues predicate. A value that fails the test causes a ServerExchangeRejectedException naming the header key and offending value. This blocks CRLF injection and other header-value smuggling attacks.
Solutions
- Sanitize the header value on the client: strip CR/LF and control/non-ASCII characters before sending.
- Review the rejected value in logs and relax the setAllowedHeaderValues predicate if the value is legitimate (e.g. allow printable ASCII).
- Fix intermediary proxies/servers that append or rewrite the header with illegal characters.
- If it's an attack probe, block the source; the firewall is working as intended.
Example fix
// before: client sets raw user input in header
request.headers.set("X-Note", userInput); // may contain \n or control chars
// after
request.headers.set("X-Note",
userInput.replaceAll("[\\r\\n\\x00-\\x1F]", "")); Defensive patterns
Strategy: validation
Validate before calling
boolean isSafeHeaderValue(String value) {
return value != null && value.matches("[\\x20-\\x7E]+") && !value.contains("\r") && !value.contains("\n");
} Try / catch
try {
exchange = firewall.getFirewalledExchange(exchange);
} catch (ServerExchangeRejectedException e) {
log.warn("Rejected header value: {}", e.getMessage());
return ResponseEntity.badRequest().build();
} Prevention
- Strip CR/LF and control characters from header values before setting them.
- Restrict header values to printable ASCII or properly encode them.
- Never put unvalidated user input into header values.
- Test custom allowedHeaderValues predicates with edge-case values (newline, unicode, empty).
When it happens
Trigger: A request header (key) has a value failing allowedHeaderValues — typically values containing CR/LF, non-printable characters, non-ASCII text, or control characters inserted by clients or intermediaries.
Common situations: Users pasting multi-line content into a header value (e.g. custom tracing or locale headers); clients setting values with unencoded Unicode; proxies appending suspicious values; overly strict custom allowedHeaderValues predicates rejecting legitimate values after a config change.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- The request was rejected because the header name
- Could not parse 'Accept' header
- DigestAuthenticationFilter.nonceCompromised
- Invalid remember-me token (Series/token) mismatch. Implies…
- SAML payload exceeded maximum size of
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/0f33e83583c1ed3f.
Report an issue: GitHub.
Appendix: source
Thrown at web/src/main/java/org/springframework/security/web/server/firewall/StrictServerWebExchangeFirewall.java:642
if (!isNormalized(request.getURI().getRawPath())) {
return false;
}
if (!isNormalized(request.getURI().getPath())) {
return false;
}
return true;
}
private void validateAllowedHeaderName(String headerNames) {
if (!StrictServerWebExchangeFirewall.this.allowedHeaderNames.test(headerNames)) {
throw new ServerExchangeRejectedException(
"The request was rejected because the header name \"" + headerNames + "\" is not allowed.");
}
}
private void validateAllowedHeaderValue(Object key, @Nullable String value) {
if (!StrictServerWebExchangeFirewall.this.allowedHeaderValues.test(value)) {
throw new ServerExchangeRejectedException("The request was rejected because the header: \"" + key
+ " \" has a value \"" + value + "\" that is not allowed.");
}
}
private void validateAllowedParameterName(String name) {
if (!StrictServerWebExchangeFirewall.this.allowedParameterNames.test(name)) {
throw new ServerExchangeRejectedException(
"The request was rejected because the parameter name \"" + name + "\" is not allowed.");
}
}
private void validateAllowedParameterValue(String name, String value) {
if (!StrictServerWebExchangeFirewall.this.allowedParameterValues.test(value)) {
throw new ServerExchangeRejectedException("The request was rejected because the parameter: \"" + name
+ " \" has a value \"" + value + "\" that is not allowed.");
}
}
View on GitHub (pinned to 96852e8860)