spring-projects/spring-security · error · ServerExchangeRejectedException
The request was rejected because the header name
Error message
The request was rejected because the header name "<headerNames>" is not allowed.
What it means
The firewall validates every request header name against the allowedHeaderNames predicate. A header whose name fails the predicate is rejected with ServerExchangeRejectedException. This blocks header-injection attacks using malformed or illegal header names.
Solutions
- Inspect the rejected header name in the logs and remove/fix it on the client that sends it.
- If the header is legitimate, widen allowedHeaderNames via firewall.setAllowedHeaderNames(name -> name.matches("[a-zA-Z0-9-]+")) or similar safe pattern.
- Fix proxy/middleware config that injects malformed header names.
- Encode the header name to valid HTTP token characters at the source.
Example fix
// before
StrictServerWebExchangeFirewall firewall = new StrictServerWebExchangeFirewall();
// after: allow standard token header names plus a custom one
firewall.setAllowedHeaderNames(name ->
name.matches("[A-Za-z0-9-]+") || name.equals("X-Custom-Id")); Defensive patterns
Strategy: validation
Validate before calling
boolean isSafeHeaderName(String name) {
return name != null && name.matches("[A-Za-z0-9-]+") && name.length() <= 128;
} Try / catch
try {
exchange = firewall.getFirewalledExchange(exchange);
} catch (ServerExchangeRejectedException e) {
log.warn("Rejected header name: {}", e.getMessage());
return ResponseEntity.badRequest().build();
} Prevention
- Only send standard HTTP token header names (letters, digits, hyphens).
- Audit middleware/proxies for headers they inject.
- Keep a documented allowlist of custom headers and test against the firewall config.
- Never construct header names dynamically from user input.
When it happens
Trigger: A request carries a header whose name does not pass allowedHeaderNames — e.g. custom headers with invalid characters, headers containing non-ASCII or control characters, or a default predicate rejecting the name of a header a client/proxy adds.
Common situations: Clients sending unusual custom headers (X-Foo with weird casing/characters) during migration from a less strict setup; middleware adding headers the firewall's default predicate rejects; upgrading Spring Security where default header-name rules tightened; typo'd header names generated dynamically.
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 request was rejected because the domain
- The request was rejected because the header
- The request was rejected because the parameter name
- The request was rejected because the URL was not normalized.
- The requestURI cannot contain encoded slash. Got " +…
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/f8a0ba45b612d00b.
Report an issue: GitHub.
Appendix: source
Thrown at web/src/main/java/org/springframework/security/web/server/firewall/StrictServerWebExchangeFirewall.java:635
return result;
}
private boolean isNormalized(ServerHttpRequest request) {
if (!isNormalized(request.getPath().value())) {
return false;
}
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.");
}
}
View on GitHub (pinned to 96852e8860)