Diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Refresh the server configs and drop unsafe-inline
style-src allowed inline styles only for the diffstat bars, which take
their width from colspan instead. t0004 now checks that the three
configs pin the same policy.
Diffstat (limited to 'custom/servers/nginx.conf')
| -rw-r--r-- | custom/servers/nginx.conf | 73 |
1 file changed, 30 insertions, 43 deletions
diff --git a/custom/servers/nginx.conf b/custom/servers/nginx.conf index cf1e49f..3ffa2ba 100644 --- a/custom/servers/nginx.conf +++ b/custom/servers/nginx.conf @@ -16,8 +16,7 @@ # PATH_INFO and reads page options such as h= and id= from QUERY_STRING, so # nginx must pass PATH_INFO through to the binary. cgit builds its own link # base from SCRIPT_NAME. The five static assets are served straight off disk -# and must never be routed through cgit. Passing PATH_INFO through is the -# single most important part of the config below. +# and must never be routed through cgit. # # nginx cannot run CGI programs itself, so a small bridge called fcgiwrap runs # the cgit.cgi binary and speaks FastCGI to nginx. Nothing below works until @@ -48,11 +47,10 @@ events { http { - # nginx's compiled-in type table knows only text/html, and the usual - # "include mime.types" would pull in a second file. Exactly five static - # files are served off disk, so their types are declared here instead and - # this config keeps standing on its own. Everything else nginx returns - # comes from cgit, which sets its own Content-Type. + # nginx's built-in type table covers none of these five extensions, and + # the usual "include mime.types" would pull in a second file, so the five + # types are declared here. Everything else nginx returns comes from cgit, + # which sets its own Content-Type. types { text/css css; text/javascript js; @@ -80,14 +78,11 @@ http { gzip_types text/css text/javascript text/plain application/atom+xml; - # Requests carrying a Host header this config does not serve, a raw IP or - # an invented name from a scanning bot, land in these two blocks and are - # dropped without a response. cgit keys its page cache on the Host header - # so clone URLs stay honest, which means every invented hostname reaching - # it would mint a cache entry of its own and evict a real page to make - # room. Refusing strangers here keeps the cache to the names the site - # actually answers to. 444 is nginx shorthand for closing the connection - # without replying. + # Requests carrying a Host header this config does not serve are dropped + # without a response. cgit keys its page cache on the Host header, so + # every invented hostname reaching it would mint a cache entry of its + # own and evict a real page. 444 is nginx shorthand for closing the + # connection without replying. server { listen 80 default_server; listen [::]:80 default_server; @@ -158,8 +153,9 @@ http { # Site-wide security headers sit here because they must also cover the # static assets nginx serves directly. cgit itself sends only the # headers the proxy cannot supply. Those are Status, Content-Type, - # Content-Length and Content-Disposition on downloads, a no-store - # Cache-Control on unauthenticated responses, the auth filter's + # Content-Length and Content-Disposition on downloads, Location on + # redirects, a no-store Cache-Control on unauthenticated responses, + # the auth filter's # Set-Cookie, and on raw repository bytes a nosniff of its own next to # the stricter policy "default-src 'none'". Everything else, this # policy included, is the proxy's job. @@ -170,13 +166,13 @@ http { # construct that rewrites response headers here could strip the # protection cgit puts on raw repository content. # - # cgit loads only its own /cgit.js and uses inline style on the - # diffstat bars, so script-src stays self while style-src allows - # inline. form-action self covers the login form, the only form cgit + # form-action self covers the login form, the only form cgit # renders. always applies them to error responses too. If you enable # the gravatar or libravatar avatar filter, add its host to img-src, # for example https://www.gravatar.com or https://seccdn.libravatar.org. - add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'self'; form-action 'self'" always; + # A head-include or repo.head-content that injects a <style> block + # needs 'unsafe-inline' added to style-src. + add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'self'; form-action 'self'" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer" always; @@ -203,8 +199,7 @@ http { # The document root is the directory that holds the static assets. cgit # emits absolute links to /cgit.css and /cgit.png by default, so those - # files must resolve at the root of the URL space. Pointing root at the - # asset directory makes /cgit.css map to /usr/share/cgit/cgit.css. + # files must resolve at the root of the URL space. root /usr/share/cgit; # The only request body cgit ever reads is the auth-filter login form, @@ -216,15 +211,11 @@ http { error_log /var/log/nginx/cgit.error.log; # Match the assets by their exact root-level names, never by bare - # extension. cgit routes on PATH_INFO and a repository can hold files - # ending in .css or .png, so /myrepo/tree/style.css and /myrepo/plain/ - # logo.png are real cgit URLs. A broad extension match would capture - # those, look for them on disk, and return 404 before cgit could render - # them. Anchoring the regex at the start of the path matches /cgit.css - # but not /myrepo/tree/cgit.css, so it can never shadow a repository - # file. An nginx regex location is matched before the prefix location - # below, so these assets win for their exact URLs and cgit wins for the - # rest. + # extension. A repository can hold files ending in .css or .png, and + # /myrepo/tree/style.css is a real cgit URL a broad match would + # capture and 404. The regex anchored at ^/ matches /cgit.css but + # never /myrepo/tree/cgit.css, and a regex location beats the prefix + # location below, so assets win their exact URLs and cgit the rest. location ~ ^/(cgit\.css|cgit\.js|cgit\.png|favicon\.ico|robots\.txt)$ { expires 30d; access_log off; @@ -234,13 +225,10 @@ http { # Everything that is not a static asset above is a cgit URL, the repo # index, a repository, a page within a repository, a snapshot, a feed. location / { - # The CGI environment. This is normally "include fastcgi_params", - # which would be a second file, so the list is written out here. - # Of all of it cgit itself reads only CGIT_CONFIG, PATH_INFO, - # QUERY_STRING, SCRIPT_NAME, REQUEST_METHOD, CONTENT_LENGTH, - # HTTP_HOST, HTTPS, SERVER_NAME, SERVER_PORT, HTTP_COOKIE and - # HTTP_REFERER. The cookie and referer arrive on their own, since - # nginx forwards request headers as HTTP_* without being asked. + # The CGI environment, normally "include fastcgi_params", written + # out here so this config stands alone. The cookie and referer + # arrive on their own, since nginx forwards request headers as + # HTTP_* without being asked. # The program fcgiwrap runs. It must be the cgit binary itself, not # $document_root$fastcgi_script_name, which would try to run a repo @@ -291,8 +279,7 @@ http { fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; - # Hand off to the fcgiwrap socket. A TCP fcgiwrap would use for - # example 127.0.0.1:9000 here. + # Hand off to the fcgiwrap socket. fastcgi_pass unix:/run/fcgiwrap.socket; # Large outputs such as snapshot tarballs and blame on big files @@ -300,8 +287,8 @@ http { fastcgi_read_timeout 300s; fastcgi_buffering off; - # cgit sends no caching headers of its own, so browsers refetch - # dynamic pages and cgit's internal cache keeps that cheap. Do not + # Ordinary cgit pages carry no caching headers, so browsers + # refetch them and cgit's internal cache keeps that cheap. Do not # add a blanket expires or Cache-Control in this location. It # would fight the no-store cgit puts on the login page and could # let one visitor's page be served to another from a shared cache. |
