diff --git a/internal/dockeragent/agent_collect_test.go b/internal/dockeragent/agent_collect_test.go index 5e7f2cc63..dd156afa3 100644 --- a/internal/dockeragent/agent_collect_test.go +++ b/internal/dockeragent/agent_collect_test.go @@ -563,6 +563,29 @@ func TestCollectContainer(t *testing.T) { } }) + t.Run("oversized stats response", func(t *testing.T) { + agent := &Agent{ + docker: &fakeDockerClient{ + containerInspectWithRawFn: func(context.Context, string, bool) (containertypes.InspectResponse, []byte, error) { + inspect := baseInspect() + inspect.State = &containertypes.State{Running: true} + return inspect, nil, nil + }, + containerStatsOneShotFn: func(context.Context, string) (dockerStatsResponseReader, error) { + return dockerStatsResponseReader{ + Body: io.NopCloser(strings.NewReader(strings.Repeat("x", maxContainerStatsBodyBytes+1))), + }, nil + }, + }, + logger: logger, + } + + _, err := agent.collectContainer(context.Background(), containertypes.Summary{ID: "container-123456"}) + if err == nil || !strings.Contains(err.Error(), "response body exceeds") { + t.Fatalf("collectContainer() error = %v, want response size limit error", err) + } + }) + t.Run("uptime negative clamped", func(t *testing.T) { future := time.Now().Add(5 * time.Minute).Format(time.RFC3339Nano) inspect := baseInspect() diff --git a/internal/dockeragent/collect.go b/internal/dockeragent/collect.go index ac8b3582c..ef318a2c9 100644 --- a/internal/dockeragent/collect.go +++ b/internal/dockeragent/collect.go @@ -5,7 +5,6 @@ import ( "crypto/rand" "encoding/json" "fmt" - "io" "math" "math/big" "net/netip" @@ -591,7 +590,7 @@ func (a *Agent) collectContainer(ctx context.Context, summary containertypes.Sum } }() - payload, err := io.ReadAll(statsResp.Body) + payload, err := readBodyWithLimit(statsResp.Body, maxContainerStatsBodyBytes) if err != nil { return agentsdocker.Container{}, fmt.Errorf("read stats: %w", err) } diff --git a/internal/dockeragent/http_limits.go b/internal/dockeragent/http_limits.go index 03553ce9c..4a4673fa9 100644 --- a/internal/dockeragent/http_limits.go +++ b/internal/dockeragent/http_limits.go @@ -10,6 +10,7 @@ const ( maxVersionResponseBodyBytes = 64 * 1024 maxRegistryManifestBodyBytes = 4 * 1024 * 1024 maxRegistryTokenBodyBytes = 1 * 1024 * 1024 + maxContainerStatsBodyBytes = 4 * 1024 * 1024 ) func readBodyWithLimit(r io.Reader, maxBytes int64) ([]byte, error) {