Skip to content

Commit 66bcb81

Browse files
authored
Check HTTP status before parsing response body (#673)
1 parent a275db4 commit 66bcb81

2 files changed

Lines changed: 26 additions & 0 deletions

File tree

internal/decode/decoder.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ func fetchHTTPDirectly(u *url.URL) ([]byte, error) {
150150
return nil, err
151151
}
152152
defer r.Body.Close()
153+
154+
if r.StatusCode != http.StatusOK {
155+
sanitized := fmt.Sprintf("%s://%s%s", u.Scheme, u.Host, u.Path)
156+
return nil, fmt.Errorf("failed to fetch %s: received HTTP %d", sanitized, r.StatusCode)
157+
}
158+
153159
data, err := io.ReadAll(r.Body)
154160
if err != nil {
155161
return nil, err

internal/decode/decoder_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,26 @@ func TestDecoderFromURL(t *testing.T) {
6868
require.NoError(t, err)
6969
require.Equal(t, schemaContent, vFile.Schema.Schema)
7070
})
71+
72+
t.Run("HTTP 404 returns an error instead of parsing response body", func(t *testing.T) {
73+
u, err := url.Parse(serverURL + "/nonexistent")
74+
require.NoError(t, err)
75+
76+
_, err = FetchFromURL(u)
77+
require.Error(t, err)
78+
require.Contains(t, err.Error(), "HTTP 404")
79+
})
80+
81+
t.Run("error message does not leak query parameters", func(t *testing.T) {
82+
u, err := url.Parse(serverURL + "/nonexistent?token=secret&key=private")
83+
require.NoError(t, err)
84+
85+
_, err = FetchFromURL(u)
86+
require.Error(t, err)
87+
require.NotContains(t, err.Error(), "secret")
88+
require.NotContains(t, err.Error(), "private")
89+
require.Contains(t, err.Error(), "/nonexistent")
90+
})
7191
}
7292

7393
func TestRewriteURL(t *testing.T) {

0 commit comments

Comments
 (0)