Fading Coder

One Final Commit for the Last Sprint

Home > Notes > Content

Handling invalid request target characters in Tomcat 8.5+ under RFC 7230/3986

Notes 4

Symptom

Upgrading to Tomcat 8.5+ (including the embedded Tomcat in Spring Boot) may reject requests whose path or query contains characters such as {, }, [, ], |, \ and others. A typical failure looks like:

java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:467)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:667)
    ...

Why it happens

Newer Tomcat releases enforce RFC 7230/3986 parsing rules more strictly. RFC 3986 limits unencoded characters in the request target to:

  • Unreserved: A–Z, a–z, 0–9, '-', '.', '_', '~'
  • Rseerved delimiters when used with proper semantics
  • Everything else must be percent-encoded

Tomcat 8.5+ additionally blocks a conservative set of ASCII characters in the path and query unless explicitly allowed or percent-encoded. This commonly impacts braces {}, square brackets [], pipe |, backslash \ , caret ^, backtick `, double quote ", and angle brackets <>.

Remediation options

  • Encode on the client side (preferred)

    • Ensure all dynamic path segments and query parameter values are percent-encoded.
    • Examples:
      • JavaScript (query values):
        const raw = 'msg=name|id{}[]';
        const url = '/api/search?q=' + encodeURIComponent(raw);
        fetch(url);
        
      • Java (query values):
        String raw = "name|id{}[]";
        String q = java.net.URLEncoder.encode(raw, java.nio.charset.StandardCharsets.UTF_8.name());
        String url = "/api/search?q=" + q;
        
  • Reconfigure Tomcat parsing (when encoding cannot be applied everywhere)

    • Global (standalone Tomcat): add allowed characters via system property in conf/catalina.properties. Supported in Tomcat 7.0.76+, 8.0.42+, 8.5.12+; later versions deprecate this in favor of connector attributes.
      # conf/catalina.properties
      tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}
      
    • Connector attributes (Tomcat 8.5+): relax the validator for specific characters.
      • server.xml example:
        <Connector
            port="8080"
            protocol="org.apache.coyote.http11.Http11NioProtocol"
            relaxedPathChars="[]|"
            relaxedQueryChars="[]|{}^\`&quot;&lt;&gt;" />
        
        Note: In XML, backslash, quotes, and angle brackets must be escaped as shown; Tomcat interprets the actual characters at runtime.
  • Downgrade to Tomcat 7 (not recommended)

    • Only as a temporary workaround; stricter parsing is more standards-compliant and safer.

Spring Boot embedded Tomcat configuration

Spring Boot 1.5.x

Define a customizer to set connector attributes at startup.

import org.apache.catalina.connector.Connector;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RelaxedCharsTomcatCustomizer implements EmbeddedServletContainerCustomizer {

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        if (container instanceof TomcatEmbeddedServletContainerFactory) {
            TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container;
            tomcat.addConnectorCustomizers((Connector conn) -> {
                // Allow specific characters in query and path. Encode when possible.
                conn.setAttribute("relaxedQueryChars", "[]|{}^\\`\"<>");
                conn.setAttribute("relaxedPathChars",  "[]|");
            });
        }
    }
}

Spring Boot 2.x+

Use WebServerFactoryCustomizer with TomcatServletWebServerFactory.

import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TomcatWebServerConfig {

    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> allowSpecialChars() {
        return (TomcatServletWebServerFactory factory) ->
            factory.addConnectorCustomizers((Connector conn) -> {
                conn.setAttribute("relaxedQueryChars", "[]|{}^\\`\"<>");
                conn.setAttribute("relaxedPathChars",  "[]|");
            });
    }
}

Notes

  • Use the smalest set of relaxed characters needed; allowing broad sets may increase security risk.
  • The "relaxedQueryChars" and "relaxedPathChars" settings affect validation only; they do not decode. Applications must still handle encoded values correctly.
  • Prefer percent-encoding for user input in query parameters and path segments instead of relying solely on parser relaxation.

Related Articles

Designing Alertmanager Templates for Prometheus Notifications

How to craft Alertmanager templates to format alert messages, improving clarity and presentation. Alertmanager uses Go’s text/template engine with additional helper functions. Alerting rules referenc...

Deploying a Maven Web Application to Tomcat 9 Using the Tomcat Manager

Tomcat 9 does not provide a dedicated Maven plugin. The Tomcat Manager interface, however, is backward-compatible, so the Tomcat 7 Maven Plugin can be used to deploy to Tomcat 9. This guide shows two...

Skipping Errors in MySQL Asynchronous Replication

When a replica halts because the SQL thread encounters an error, you can resume replication by skipping the problematic event(s). Two common approaches are available. Methods to Skip Errors 1) Skip a...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.