check / check (push) Failing after 2m18s
Add Quality and FitMode to signature.Request, not yet part of the signed data, and tests that a signature for quality 85 and fit cover is refused when replayed with another quality or fit: one against Signer.Verify, one through the image route. The route test also sends the same signature with no q or fit and with q=85&fit=cover, which must both pass, and sends URLs built by imgcache.Service.GenerateSignedURL. The replay cases fail until the next commit. Model: opus-4-8 (implementation); opus-5-5 (rework)
69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
package signature_test
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"sneak.berlin/go/pixa/internal/signature"
|
|
)
|
|
|
|
// signedQualityFitRequest returns a request signed for quality 85 and fit
|
|
// mode "cover", the effective defaults the handler applies before
|
|
// verification.
|
|
func signedQualityFitRequest(signer *signature.Signer) *signature.Request {
|
|
req := &signature.Request{
|
|
SourceHost: testHost,
|
|
SourcePath: testPath,
|
|
Width: 800,
|
|
Height: 600,
|
|
Format: testFormatWebP,
|
|
Quality: 85,
|
|
FitMode: testFitCover,
|
|
Expires: time.Now().Add(1 * time.Hour),
|
|
}
|
|
req.Signature = signer.Sign(req)
|
|
|
|
return req
|
|
}
|
|
|
|
// TestSigner_Verify_QualityAndFitAreSigned proves that quality and fit are
|
|
// covered by the signature: a URL signed for one quality or fit mode must
|
|
// not verify when replayed with a different quality or fit mode. This is the
|
|
// amplification vector from the issue — one signed URL replayed across many
|
|
// quality and fit values yields many unauthorized cache entries and
|
|
// transcodes — so it must be rejected.
|
|
func TestSigner_Verify_QualityAndFitAreSigned(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
signer := signature.New("test-secret-key")
|
|
|
|
cases := []struct {
|
|
name string
|
|
tamper func(r *signature.Request)
|
|
}{
|
|
{
|
|
name: "replayed with different quality",
|
|
tamper: func(r *signature.Request) { r.Quality = 40 },
|
|
},
|
|
{
|
|
name: "replayed with different fit mode",
|
|
tamper: func(r *signature.Request) { r.FitMode = testFitContain },
|
|
},
|
|
}
|
|
|
|
for _, tt := range cases {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
req := signedQualityFitRequest(signer)
|
|
tt.tamper(req)
|
|
|
|
err := signer.Verify(req)
|
|
if !errors.Is(err, signature.ErrInvalid) {
|
|
t.Errorf("Verify() = %v, want %v", err, signature.ErrInvalid)
|
|
}
|
|
})
|
|
}
|
|
}
|