From 03e028e79f9086f1ddfe1b8c0923cdbc9cb4aba0 Mon Sep 17 00:00:00 2001 From: Karthik Chowdary <21139050+Karthik-Chowdary@users.noreply.github.com> Date: Wed, 2 Sep 2026 09:24:48 +0000 Subject: [PATCH] source/http: report errors before checksum mismatch Pinned HTTP sources download their payload during Snapshot. Check the response status there before saving the error response as a snapshot and reporting its digest as a checksum mismatch. Add a regression test proving a 403 response reports its status instead of a misleading digest mismatch. Signed-off-by: Karthik Chowdary <21139050+Karthik-Chowdary@users.noreply.github.com> --- source/http/source.go | 3 +++ source/http/source_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/source/http/source.go b/source/http/source.go index 858805358d45..16de254dfbd5 100644 --- a/source/http/source.go +++ b/source/http/source.go @@ -896,6 +896,9 @@ func (hs *httpSourceHandler) Snapshot(ctx context.Context, jobCtx solver.JobCont defer func() { _ = resp.Body.Close() }() + if resp.StatusCode < 200 || resp.StatusCode >= 400 { + return nil, errors.Errorf("invalid response status %d", resp.StatusCode) + } ref, dgst, err := hs.save(ctx, resp, g) if err != nil { diff --git a/source/http/source_test.go b/source/http/source_test.go index 01eb9335a021..f015d2b4351e 100644 --- a/source/http/source_test.go +++ b/source/http/source_test.go @@ -2,6 +2,8 @@ package http import ( "context" + "net/http" + "net/http/httptest" "os" "path/filepath" "testing" @@ -315,6 +317,31 @@ func TestHTTPChecksum(t *testing.T) { ref = nil } +func TestHTTPChecksumReturnsResponseStatus(t *testing.T) { + t.Parallel() + ctx := t.Context() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte("forbidden response body")) + })) + defer server.Close() + + hs, err := newHTTPSource(t) + require.NoError(t, err) + id := &HTTPIdentifier{ + URL: server.URL + "/artifact", + Checksum: digest.FromString("expected"), + } + h, err := hs.Resolve(ctx, id, nil, nil) + require.NoError(t, err) + _, _, _, _, err = h.CacheKey(ctx, nil, 0) + require.NoError(t, err) + + _, err = h.Snapshot(ctx, nil) + require.ErrorContains(t, err, "invalid response status 403") +} + func TestHTTPSignatureVerification(t *testing.T) { t.Parallel() ctx := t.Context()