3.7.2
π‘οΈ Hardening release β deploy pipeline, security and safer defaults
Deploy pipeline
- Tagged releases are now test-gated: the tag build runs ruff, ty and pytest before any image is pushed or deployed.
- The prod deploy now checks out the pushed tag (previously a bare
git pullofmain) and pins services to the released image version, so prod runs exactly what the tag built. - The fixed 120 s image-propagation wait was replaced with a registry manifest poll.
- The generated prod
.envcan no longer crash the stack: empty (unset) GitHub variables fall back to defaults instead of failing onint("")at import.
Security
- Decompression-bomb guard: images whose headers declare more than 64 megapixels are rejected before any pixel decoding, with a clean per-analyzer error β previously a crafted ~1 MB PNG could OOM the worker or silently kill an analyzer thread.
/downloadand/imageβ previously the only uncapped data routes β are now rate-limited.- Baseline security headers (
X-Content-Type-Options,X-Frame-Options,Referrer-Policy,Permissions-Policy) are sent on every response. - Upload logs (IP + User-Agent) are now swept after the standard 3-day retention window instead of being kept forever.
Ops & self-hosting
.env.exampleno longer shipsCLEAR_AT_RESTART=1β which silently wiped a self-hosted instance's database and results on every restart β and no longer carries live AdSense ids: ads are strictly opt-in.- Log rotation and memory limits on all compose services; the rq-dashboard container is pinned (v0.6.3) and only receives its Redis URL instead of the full
.env. - gunicorn now runs as PID 1 and drains in-flight requests on deploy instead of being SIGKILLed.
- Images archived by the removal flow persist on a named volume across redeploys.
The full audit and remaining follow-ups are tracked in docs/improvement-plan.md.
Full changelog: 3.7.1...3.7.2