The one about proxy_pass blindly forwarding syntactically malformed requests and silently failing to process the response is astonishing.<p>It doesn't appear to be documented. Looking through NginX documentation at <a href="http://nginx.org/en/docs/http/ngx_http_proxy_module.html" rel="nofollow">http://nginx.org/en/docs/http/ngx_http_proxy_module.html</a> I don't see anything (e.g. under proxy_hide_header) to say it's sometimes not applied, and there doesn't appear to be any option to prevent this blind forwarding.<p>I would never have expected the backend to receive invalid HTTP from NginX, but more importantly it's not uncommon for backends to send an extra header or two to tell NginX how to serve the response, with NginX removing those headers before serving.<p>How do you even handle this properly? Checking for valid HTTP might not be enough, as you need to exactly match whatever NginX's idea of valid is, rather than matching the HTTP spec.
Default for root is 'html' according to the docs (which is a relative path wrt /usr/share/nginx), not /etc/nginx. <a href="http://nginx.org/en/docs/http/ngx_http_core_module.html#root" rel="nofollow">http://nginx.org/en/docs/http/ngx_http_core_module.html#root</a><p>I guess it may depend on how nginx was configured during build. But for example on Debian this is not an issue.
I realize that, at best, this is only tangentially related to security, but nginx's logging is quite frustrating. It'll log something that's completely out of your control (like invalid SSL requests) as a [crit]<p>You end up having patterns in your log ingestion to drop errors. Or, and this is the security concern, you start to ignore nginx errors.
A common pit I fell into is the <i>"inheritance"</i> of add_header. If you use <i>a single</i> add_header at a lower level <i>all</i> add_headers at the higher levels are ignored for that server or location.<p>As some headers have security implications this is an easy way to shoot yourself in the foot.<p>Another security related point is the suppression of the server version. While nginx can omit the version number out-of-the-box, you unfortunately need an extension to remove the header completely.
This is a good example of the trade off between pretty/terse/clever and safe/correct/maintainable. Nginx is well-respected mature software but it's hard to see these issues as anything other than a design blunder. The trailing-slash path traversal thing looks to me like a file system analogue of SQL injection.<p>I think d3.js is another example of this. It's obviously written with incredible skill but I could never get on with the ultra declarative and implicit style, it always felt like a fight.<p>These days there seems to be a trend towards a verbose, explicit style, e.g. Zig (no hidden control flow - compare to C++'s operator overload-fest) and Go.
A lot of these look like not-so-great design choices in the way nginx is configured and how it handles paths.<p>Sometimes the behavior that leads to security problems here may be desirable, but it probably shouldn't be the default.<p>For instance "location /api {" probably shouldn't match "/api../" by default. Instead it should be treated like a file system would. The "prefix" matching should be
a different configuration option like "prefix /api {".
I would recommend giving Caddy[0] a try.<p>Most servers/reverse proxies need 10s of options to work <i>more or less</i> well. With Caddy, "correct" is the default, including having the best SSL management system (so you don't even need certbot) I've seen, and using HTTPS by default. It's true that it has some things missing (rate-limitng and weighted load balancing to name a few) that you can do in Nginx/Traefik/etc, but it's 100% worth it. Caddy also has a great extension system, so those things could easily be created as extensions.<p>[0] <a href="https://caddyserver.com/" rel="nofollow">https://caddyserver.com/</a>
Though deprecated, <a href="https://github.com/yandex/gixy" rel="nofollow">https://github.com/yandex/gixy</a> is a nice checker for these kind of issues.
There was a follow-up to this released last week by Frans Rosen on Detectify Labs that looked into middleware in general and still applicable to nginx: <a href="https://labs.detectify.com/2021/02/18/middleware-middleware-everywhere-and-lots-of-misconfigurations-to-fix/" rel="nofollow">https://labs.detectify.com/2021/02/18/middleware-middleware-...</a>
This confabulated configuration syntax is why I discontinued using NGINX.<p>This selection of NGINX came after a frustrated debugging session of Apache .htaccess as well.<p>furthermore, unlike Apache specific IP port assignment capability, I once had to jerry-rig a dynamic configuration to tie NGINX to just one dynamic IP port out of many.<p>Sorry, I’ve gone lighttpd and haven’t looked back since.
I've been running Nginx for more then 10 years now... Is there anything "new"? I know about serverless, but anything else that makes the webserver part easier and safe?