Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question/feature: adding a configuration flag to set whether NGiNX should decode percent-encoded characters in URI or not #501

Open
mikyll opened this issue Feb 7, 2025 · 0 comments
Labels

Comments

@mikyll
Copy link

mikyll commented Feb 7, 2025

Note

I'm not a security expert and I don't know if that feature might generate vulnerabilities or anything similar (e.g. path traversal attacks). If that's the case, you can directly close or delete the issue, but I'd love to be redirected to some relevant documentation on the topic and/or to receive some guidance on how to approach this task in the correct way 🙂

Describe the feature you'd like to add to nginx

I'd like to introduce a configuration flag named decode_percent_characters (or something similar):

  • by default set to on, so that it doesn't change NGiNX default behaviour;
  • similarly to merge_slashes, it's passed to ngx_http_parse_complex_uri();
  • if set to off, NGiNX doesn't replace percent-encoded characters in request URIs, with their respective decoded values (i.e. %2f doesn't get decoded to / if we set decode_percent_characters off; in nginx.conf);

Example

Show/Hide example

Suppose we have a file /usr/local/nginx/html/path%2fslash/index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>Percent-encoded test</title>
  </head>
  <body>
    <h1>Percent-encoded test</h1>
  </body>
</html>

File /usr/local/nginx/conf/nginx.conf:

worker_processes  1;

events {
  worker_connections  1024;
}

http {
  decode_percent_characters off;
  
  server {
    listen       80;
    server_name  localhost;
  }
}

Test request:

curl "localhost:80/path%2fslash/"

Result:

<!DOCTYPE html>
<html>
  <head>
    <title>Welcome to nginx!</title>
  </head>
  <body>
    <h1>Welcome to nginx!</h1>
  </body>
</html>

Without this change we would get a 404: Not Found error, and the following log entry in /usr/local/nginx/logs/error.log:

2025/02/07 12:15:26 [error] 103512#0: *9 "/usr/local/nginx/html/path/slash/index.html" is not found (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /path%2fslash/ HTTP/1.1", host: "localhost"

Describe the problem this feature solves

With this feature, we would be able to serve pages containing percent-encoded characters in their path (e.g. /usr/local/nginx/html/path%2fslash/index.html).

Additionally, when NGiNX is used as a reverse proxy, such as when it's distributed via OpenResty and used as an API Gateway (e.g. APISIX, Kong, etc.), we can match routes that have path parameters containing percent-encoded characters, and delegate their decoding to upstreams/other web servers.
Notice that many popular web frameworks already support percent-encoded characters in path parameters:

Technology Supports %-encoded chars Usage Docs
Django (Python) 🟢 Using <path:id> Django - Path Converters
Fastapi (Python) 🟢 Using {id:path} Fastapi - Path Convertor
Flask (Python) 🟢 Using <path:id> Flask - Variable Rules
Express (JS) 🟢 Using :id (default) -
Fastify (JS) 🟢 Using :id (default) -
Actix Web (Rust) 🟢 Using {id} (default) -
ASP.NET Core (C#) 🟢 Using {id} (default) -
Spring Boot (Java) 🟢 By default requests containing %2F in path parameters return 400: Bad Request, but Tomcat can be configured to allow them -
NGiNX (C) 🔴 - -

Additional context

Some References

Feature Implementation

I already implemented two versions of this feature in a fork:

APISIX Example

With this feature, we could make APISIX correctly match routes containing %-encoded characters in path parameters (when using router radixtree_uri_with_parameters, see APISIX Docs | Router), by simply setting the following configuration in /apisix/path/conf/config.yaml:

nginx_config:
  http_configuration_snippet: |
    decode_percent_characters off;

OpenResty

Maybe there's a simpler way to handle this via OpenResty ngx_http_lua_module?

@mikyll mikyll added the feature label Feb 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant