-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Gunicorn's handling of PATH_INFO and SCRIPT_NAME can lead to security issues when placed behind a proxy #2650
Comments
Fair enough. This is a part of the spec. I think most of the time it is harmless. But what about adding a ˋ—standalone ˋ option? that would make gunicorn safer |
@benoitc Just stumbled upon this. Which spec would mandate reading script_name from the request headers? |
@itszn thanks for documenting this. Noting that Would it be possible to document adding:
It's possible that Gunicorn isn't strictly required to read the |
It seems to me that using this is the only (and a convenient) way to serve a WSGI app under a custom URI prefix without touching the app code or environment, and indeed a lot of reverse-proxy setups (including my own) are using this, so please if you are going to remove this feature at least leave an option to make this approach workable. |
it looks like this has (more or less) been addressed by 72b8970 in v22 (which incidentally breaks such a usage of the SCRIPT_NAME set by a reverse proxy; also note that FAQ WSGI Bits/How do I set SCRIPT_NAME might need an update. |
What is the recommended alternative to using the |
for now I believe the only solution is to declare the SCRIPT_NAME as an actual environment variable for the gunicorn process (so you cannot have the same gunicorn app served under different paths AFAIK) rather than passing from the the reverse proxy as a header. |
What still works is transferring secure metadata out of band, unaffected by my restriction on HTTP headers - e.g. if you are launching gunicorn via systemd, tell it to put your settings into the process environment:
Gunicorn also provides an option to insert arbitrary environment from its configuration or command line:
The 21.2.0 behaviour is still available via launching gunicorn with the option --header-map dangerous. Resort to this only after carefully investigating what your application or its framework does in terms of blindly trusting other such headers. Do note that this is just one example of such underscore headers, you can play similar games with others, depending on how the application uses them. For Nginx users this investigation is straightforward - you would have to apply explicit configuration for your application to receive such header at all. For other proxies it can be much less obviously dangerous. I suspect amending the |
@douardda Thanks, that works great. I was never quite sure how or why the For anyone wanting to set # Directly set the env variable.
raw_env = ['SCRIPT_NAME=/my-app-path']
# Or, set a default that can be overridden by a pre-exiting env variable.
import os
os.environ.setdefault('SCRIPT_NAME', '/my-app-path')
|
here's a minimal repro of the difference between gunicorn 21.2.0 and 22.0.0 with respect to a SCRIPT_NAME header, in case it's useful to anyone: #3200 |
This might not be something you can fix, but I wanted to report it since people might have vulnerable configs.
Gunicorn reads some WSGI variables from request headers. This can be an issue when a proxy allows and passes along these special header values.
For example
SCRIPT_NAME
is used to transformPATH_INFO
. If a proxy previously parsed the request path to determine if access is allowed, and attacker could now use aSCRIPT_NAME
header to bypass the proxy.Here is an example nginx config:
This request will call the
/admin/something/bad
route in the WSGI app despite nginx'sdeny all
.The text was updated successfully, but these errors were encountered: