diff --git a/routers/api/actions/artifactsv4.go b/routers/api/actions/artifactsv4.go index a7befae91d8..93c892573d7 100644 --- a/routers/api/actions/artifactsv4.go +++ b/routers/api/actions/artifactsv4.go @@ -290,13 +290,22 @@ func (r *artifactV4Routes) findArtifactByName(ctx *ArtifactContext, runID int64, return &art, nil } +// maxProtobufBodySize caps the Twirp request body size accepted by parseProtobufBody. +// These requests only ever carry a handful of small scalar fields (run IDs, artifact +// names, etc.), so this is far above any legitimate payload while still bounding memory use. +const maxProtobufBodySize = 1024 * 1024 // 1 MiB + func (r *artifactV4Routes) parseProtobufBody(ctx *ArtifactContext, req protoreflect.ProtoMessage) bool { - body, err := io.ReadAll(ctx.Req.Body) + body, err := io.ReadAll(io.LimitReader(ctx.Req.Body, maxProtobufBodySize+1)) if err != nil { log.Error("Error decode request body: %v", err) ctx.HTTPError(http.StatusInternalServerError, "Error decode request body") return false } + if len(body) > maxProtobufBodySize { + ctx.HTTPError(http.StatusRequestEntityTooLarge, "request body too large") + return false + } err = protojson.Unmarshal(body, req) if err != nil { log.Error("Error decode request body: %v", err)