P1 security: q and fit are outside the HMAC signature, allowing 500x cache/transcode amplification from one signed URL #60
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Verified against
mainat61f42e6.Signer.buildSignatureData(internal/signature/signature.go:99-111) signs exactly:Neither
q(quality) norfitis included. Butinternal/handlers/image.go:50-63reads both from the query string after signature validation, and both are part of the variant cache key (internal/imgcache/storage.go:327-328—req.Quality,req.FitMode).Consequence: a single valid signed URL can be replayed with
q=1..100andfitin {cover,contain,fill,inside,outside}, yielding 500 distinct cache entries and 500 libvips transcodes that the signature was never meant to authorize. That is disk amplification against the cache budget #51 just introduced, plus CPU/memory amplification against the processing path — from one URL, by anyone who has seen it.This also makes the README false.
README.md:69-73states signatures are "exact match only: every component (host, path, query, dimensions, format, expiration) must match exactly what was signed", and the repo has an explicit exact-match-only enforcement commitment from #40.Definition of done
q/fiton signature-authenticated requests with a 400.README.md's signature specification section (both the field list and the worked example), and regenerate/extend the golden vectors ininternal/signature/golden_test.go. Note this is a breaking change to the URL signing scheme — any external signer must be updated in lockstep. Call that out in the PR body.q=85is rejected (or produces a different signature) when replayed withq=40.make checkgreen.Notes
/v1/e/encrypted-URL path is unaffected by this specific issue (the whole payload is sealed), but see the separate issue on/v1/e/input validation.