mirror of
https://github.com/projectsend/projectsend.git
synced 2026-09-16 16:45:07 +00:00
9192779ee4
Four unrelated one-liners, each already written down and none of them worth a branch of its own. The lock was still pinned to the community package's previous commit, which is the one before it started shipping its own sixteen catalogues. The mechanism that carries a package's translations to the browser landed here last week; without this bump the release would have shipped that mechanism with nothing to carry, and the Custom Assets screen would have stayed half-English in every language. The stock `local` disk had `serve` left on. Nothing in this application writes to it, so the framework's /storage route was a door with nothing behind it — but it was still a door, and closing it costs one word. nginx evaluated `\.php$` before `/protected-files/`, so a protected path ending in .php would have reached the PHP handler instead of streaming under the sandbox headers that block sets. Not reachable on a default install — the upload allowlist refuses php and X-Accel paths are UUIDs — but the guarantee read stronger than it was. `^~` makes it true. And `.release-build` is now ignored by eslint, so linting after building a zip stops walking the vendored minified JS inside it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
66 lines
2.6 KiB
Nginx Configuration File
66 lines
2.6 KiB
Nginx Configuration File
server {
|
|
listen 80;
|
|
server_name _;
|
|
root /var/www/html/public;
|
|
index index.php;
|
|
|
|
client_max_body_size 100m;
|
|
|
|
# The nginx version number is nobody's business but ours.
|
|
server_tokens off;
|
|
|
|
# Baseline hardening for every response. `always` so they survive error
|
|
# responses too. NOTE: nginx does not merge add_header across levels —
|
|
# a location that declares any add_header of its own inherits none of
|
|
# these, so /protected-files/ below repeats them deliberately.
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.php?$query_string;
|
|
}
|
|
|
|
# Protected file serving: PHP authorizes, nginx streams (brief §3).
|
|
# PHP responds with X-Accel-Redirect: /protected-files/<path>.
|
|
#
|
|
# This is the only location that returns bytes someone else uploaded,
|
|
# so it gets the strictest headers in the file. `sandbox` puts anything
|
|
# rendered as a document into an opaque origin with scripts disabled —
|
|
# if a payload ever does reach here with a renderable content type
|
|
# (FileThumbnailController's allowlist is the primary defence), it
|
|
# cannot touch this app's origin or the viewer's session. Images loaded
|
|
# as subresources are unaffected: a CSP on a subresource response never
|
|
# creates a browsing context, so thumbnails and previews still render.
|
|
# `^~` so this prefix beats the `\.php$` regex below: without it a
|
|
# protected path ending in .php would be handed to the PHP handler
|
|
# instead of streaming under the sandbox headers this block sets.
|
|
location ^~ /protected-files/ {
|
|
internal;
|
|
alias /var/www/html/storage/app/files/;
|
|
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
add_header Content-Security-Policy "sandbox; default-src 'none'" always;
|
|
}
|
|
|
|
location ~ \.php$ {
|
|
# Never hand a path to PHP-FPM that isn't a real script on disk:
|
|
# without this, any URI ending in .php reaches the interpreter and
|
|
# PATH_INFO resolution decides what actually runs.
|
|
try_files $uri =404;
|
|
|
|
fastcgi_pass app:9000;
|
|
fastcgi_index index.php;
|
|
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
|
include fastcgi_params;
|
|
fastcgi_buffer_size 32k;
|
|
fastcgi_buffers 8 32k;
|
|
}
|
|
|
|
location ~ /\.(?!well-known) {
|
|
deny all;
|
|
}
|
|
}
|