Uploaded image for project: 'WildFly'
  1. WildFly
  2. WFLY-14269

Wildfly 21's “allow-unescaped-characters-in-url” ignored when HTTP2 request going through Windows hosts file

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • Major
    • None
    • 21.0.0.Final, 21.0.1.Final, 21.0.2.Final
    • Web (Undertow)
    • None
    • Hide
      • Have an entry in your Windows hosts file for the endpoint you are about to test, e.g.: 
        127.0.0.1 myappname.company.com
      • In standalone.xml have allow-unescaped-characters-in-url=true on http-listener and https-listener
      • In standalone.xml also have enable-http2=true on http-listener and https-listener**
      • On Wildfly 21.0.0.Final send a GET request with at least one | (pipe) character in the query parameters
      • In latest Chrome (Version 87.0.4280.88 (Official Build) (64-bit)) or Firefox call a GET request with unencoded | (pipe) symbol in the query (e.g.: GET myappname.company.com/myAPI?someParam=customerId=1212090,caseId=1078841||caseId=null)
      • On Wildfly 21.0.× this will result in a ERR_HTTP2_PROTOCOL_ERROR, and a 4×× error code - with the request not even hitting the application - essentially allow-unescaped-characters-in-url is ignored
      • On Wildfly 20.0.× this works fine, as expected.
      • On Wildfly 21.0.× , when I remove enable-http2, or set it to false, it also works fine. 

       

      If you remove the entry from the hosts file though, and the request goes through the company load balancer for myappname.company.com, the request will be successful.

      Show
      Have an entry in your Windows hosts file for the endpoint you are about to test, e.g.:  127.0.0.1 myappname.company.com In standalone.xml have  allow-unescaped-characters-in-url=true on http-listener and https-listener In standalone.xml also have  enable-http2=true on http-listener and https-listener ** On  Wildfly 21.0.0.Final  send a GET request with at least one | (pipe) character in the query parameters In latest Chrome (Version 87.0.4280.88 (Official Build) (64-bit)) or Firefox call a GET request with unencoded | (pipe) symbol in the query (e.g.: GET myappname.company.com/myAPI?someParam=customerId=1212090,caseId=1078841||caseId=null) On Wildfly 21.0.× this will result in a ERR_HTTP2_PROTOCOL_ERROR, and a 4×× error code - with the request not even hitting the application - essentially allow-unescaped-characters-in-url is ignored On Wildfly 20.0.× this works fine, as expected. On Wildfly 21.0.× , when I remove enable-http2 , or set it to false, it also works fine.    If you remove the entry from the hosts file though, and the request goes through the company load balancer for myappname.company.com, the request will be successful.
    • Compatibility/Configuration
    • Workaround Exists
    • Hide

      A workaround is to encode all | (pipe) characters to %7C in requests queries, but this can't always be done if there are third-party clients using the API. 

      Show
      A workaround is to encode all | (pipe) characters to %7C in requests queries, but this can't always be done if there are third-party clients using the API. 
    • Undefined
    • ---
    • ---

    Description

      I have a Wildfly 21.0.0.Final running a Spring Boot REST application and I encountered a strange behaviour with GET requests containing | (pipe) character in the query parameters.

      | (pipe) character is unsafe according to the RFC1738 specification of HTTP, while RFC3986 allows for the encoding of Unicode characters.

      However, Wildfly (Undertow) has an option on http-listener and https-listener entries to allow-unescaped-characters-in-url.

      Full standalone.xml here with masked sensitive info.

       

      The application is running on 127.0.0.1:443, and is exposed to the outside world as https://myappname.company.com via a PulseSecure load balancer, where myappname is a CNAME registered on company.com DNS, pointing to the load balancers VIP.

      The allow-unescaped-characters-in-url="true" bit works fine in these cases (so when the request containing | doesn't go through the Windows hosts file, but goes through the load balancer).

      However, when I add an entry to the Windows hosts file to bypass the load balancer, such as:
       127.0.0.1 myappname.company.com
      …then the GET request containing | in its query parameter won't work - in fact it looks like it is not even hitting the server, as if Wildfly/Undertow's allow-unescaped-characters-in-url="true" setting wouldn't even be there.

      Now this causes issues with our local testing. Is there any change we can make so that allow-unescaped-characters-in-url="true" would be always respected?

      We know that ideally | should be encoded to %7D, but we would be interested in a solution (ideally on Wildfly level) that would make allow-unescaped-characters-in-url="true" work every time, irrespective whether the requests is going through hosts file or the load balancer.

      The very strange this is that it was working fine in Wildfly 20.0.0.Final, even without allow-unescaped-characters-in-url="true" being in standalone.xml.

       

      Full request source:

      GET /rest/v3/news/_lite?mql=customerId=1212090,caseId=1078841||caseId=null
      HTTP/1.1
      Host: myappname.company.com
      Connection: keep-alive
      Pragma: no-cache
      Cache-Control: no-cache
      sec-ch-ua: "Google Chrome";v="87", " Not;A Brand";v="99", "Chromium";v="87"
      Accept: application/json, text/plain, */*
      Authorization: Bearer masked
      sec-ch-ua-mobile: ?0
      User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
      Sec-Fetch-Site: same-origin
      Sec-Fetch-Mode: cors
      Sec-Fetch-Dest: empty
      Referer: https://myappname.company.com/anotherPage
      Accept-Encoding: gzip, deflate, br
      Accept-Language: en-GB,en;q=0.9
      Cookie: JSESSIONID=masked; _ga=GA1.2.1926489359.1609961117; _gid=masked; _gat_gtag_UA_112487518_3=1

       

      Server log excerpt with TRACE level logging attached. The faulty request is /rest/v3/news/_lite - it can be seen in one of the TRACE logs with | (pipe) symbol in its query string, but then it doesn't get "deeper", doesn't get processed at all, doesn't get logged by io.undertow.request.dump either.

      The error I get on DEBUG level:

      2021-01-08 01:32:20,660 DEBUG [io.undertow.request.io] (default I/O-7) Sending rststream on channel Http2Channel peer /127.0.0.1:50355 local /127.0.0.1:443[ No Receiver [] -- [] -- []] stream 1: java.nio.channels.ClosedChannelException
       at io.undertow.core@2.2.2.Final//io.undertow.protocols.http2.Http2Channel.sendRstStream(Http2Channel.java:1059)
       at io.undertow.core@2.2.2.Final//io.undertow.server.protocol.http2.Http2ReceiveListener.handleRequests(Http2ReceiveListener.java:135)
       at io.undertow.core@2.2.2.Final//io.undertow.server.protocol.http2.Http2ReceiveListener.handleEvent(Http2ReceiveListener.java:115)
       at io.undertow.core@2.2.2.Final//io.undertow.server.protocol.http2.Http2ReceiveListener.handleEvent(Http2ReceiveListener.java:73)
       at org.jboss.xnio@3.8.2.Final//org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
       at io.undertow.core@2.2.2.Final//io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener.handleEvent(AbstractFramedChannel.java:952)
       at io.undertow.core@2.2.2.Final//io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener.handleEvent(AbstractFramedChannel.java:932)
       at org.jboss.xnio@3.8.2.Final//org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
       at io.undertow.core@2.2.2.Final//io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener$1.run(AbstractFramedChannel.java:963)
       at io.undertow.core@2.2.2.Final//io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener.handleEvent(AbstractFramedChannel.java:939)
       at io.undertow.core@2.2.2.Final//io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener.handleEvent(AbstractFramedChannel.java:932)
       at org.jboss.xnio@3.8.2.Final//org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
       at org.jboss.xnio@3.8.2.Final//org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
       at io.undertow.core@2.2.2.Final//io.undertow.protocols.ssl.SslConduit$SslReadReadyHandler.readReady(SslConduit.java:1211)
       at io.undertow.core@2.2.2.Final//io.undertow.protocols.ssl.SslConduit$1.run(SslConduit.java:180)
       at io.undertow.core@2.2.2.Final//io.undertow.protocols.ssl.SslConduit$2.run(SslConduit.java:195)
       at org.jboss.xnio.nio@3.8.2.Final//org.xnio.nio.WorkerThread.safeRun(WorkerThread.java:612)
       at org.jboss.xnio.nio@3.8.2.Final//org.xnio.nio.WorkerThread.run(WorkerThread.java:479)

      Attachments

        Activity

          People

            flaviarnn Flavia Rainone
            mcsukas Marton Csukas
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated: