fix: harden upstream path + binary-body validation (gadfly round 1)
CI / Tidy (pull_request) Successful in 9m24s
CI / Build & Test (pull_request) Successful in 10m17s

- upstreamPath rejects '..' in model ids AND in the rest path — the rest
  can embed SERVER-SUPPLIED components (ACE-Step result file URLs), so
  dot-dot/scheme smuggling toward other proxy endpoints is refused
- singleImageResult requires positive image evidence (sniffed magic OR
  declared image/*): an empty-Content-Type error page can no longer pass
  as 'the image' via sniffImageMIME's PNG-default labelling
- upscale/background responses get a dedicated 256MB cap (the 64MB cap
  is JSON-sized; a 4x PNG legitimately exceeds it)
- mesh JSON-detection widened (512-byte whitespace-tolerant peek + reject
  declared application/json)
- Transcribe now reuses buildMultipart; transcriptionFilename takes
  (filename, mime) so diarize shares it without a fake request struct;
  truncateForError stops shadowing builtin cap; OnlyMask doc de-ambiguated

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
2026-07-13 00:50:21 -04:00
co-authored by Claude Fable 5
parent e98493bcfb
commit 4a752ffa2a
7 changed files with 89 additions and 50 deletions
+29
View File
@@ -251,3 +251,32 @@ func TestUpstreamPathRejectsSeparators(t *testing.T) {
t.Errorf("path prefix wrong: %q", got)
}
}
func TestUpscaleRejectsEmptyContentTypeNonImage(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header()["Content-Type"] = nil // suppress auto-detection: NO Content-Type at all
_, _ = w.Write([]byte("502 bad gateway"))
}))
defer srv.Close()
p := New(WithBaseURL(srv.URL), WithHTTPClient(srv.Client()))
up, _ := p.UpscaleModel("mediautils")
_, err := up.Upscale(context.Background(),
imagegen.UpscaleRequest{Image: imagegen.Image{Data: pngFixture(t)}})
var apiErr *llm.APIError
if !errors.As(err, &apiErr) {
t.Fatalf("err = %v, want APIError for headerless non-image body", err)
}
}
func TestUpstreamPathRejectsDotDot(t *testing.T) {
if _, err := upstreamPath("..", "/x"); err == nil {
t.Error("model '..' accepted")
}
if _, err := upstreamPath("m", "/v1/audio?path=../../api/models/unload"); err == nil {
t.Error("dot-dot rest accepted")
}
if _, err := upstreamPath("m", "/v1/audio?path=https://evil.example/x"); err == nil {
t.Error("absolute-URL rest accepted")
}
}