#2506 closed defect (invalid)

proxy_redirect is decoding %24

Reported by: sadiqkhoja@… Owned by:
Priority: major Milestone:
Component: nginx-core Version: 1.23.x
Keywords: proxy_pass Cc:
uname -a: Linux 060f36d625fc 5.15.0-1031-aws #35~20.04.1-Ubuntu SMP Sat Feb 11 16:19:06 UTC 2023 x86_64 GNU/Linux
nginx -V: nginx/1.23.4

Description

I have following configuration:

    location /- {
      proxy_pass http://localhost:8005/-;
      proxy_redirect off;
      proxy_set_header Host $host;
    }

When the request is <host>/-/media/%24somefile.jpg, it is passed as <backend>/-/media/$somefile.jpg. Note that %24 has been decoded into $

However if I remove /- from the proxy_pass then %24 is not decoded into $.

It looks like some sort of regex bug here. Is there a way to stop decoding of %24 into $ when there is a path in the proxy_pass.

Change History (1)

comment:1 by Maxim Dounin, 12 months ago

Resolution: invalid
Status: newclosed

As described in docs, when nginx proxies a request, the request URI is passed to the server as follows:

  1. If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive.
  1. If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI.

This is the behaviour you are seeing: with proxy_pass http://localhost:8005/-; nginx uses normalized URI, changes that part which matches the location (/-) with the URI part from the proxy_pass directive (also /- in your configuration), and then re-encodes the URI per specification requirements. Since $ is not required to be percent-encoded (see RFC 3986), it is not re-encoded, and as a result %24 is decoded to $.

If you want nginx to preserve URI as sent by the client, use proxy_pass without an URI component, that is, proxy_pass http://localhost:8005;.

Note: See TracTickets for help on using tickets.