prometheus / prometheus/common

cloneRequest does not copy the header, so round trippers mutate the caller's request

Open Beginner friendly
#981 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
295
Forks
367
Avg merge
2d 10h
Merged PRs (30d)
18

Description

cloneRequest in config/http_config.go intends a deep copy of the header but does not make one:

r2 := new(http.Request)
*r2 = *r
// Deep copy of the Header.
maps.Copy(r.Header, r2.Header)

After *r2 = *r, r2.Header is the same map as r.Header, so maps.Copy copies it onto itself. The clone shares the caller's header map.

Every round tripper that touches headers is affected, since they all clone first and then modify. headersRoundTripper uses Header.Add, so a reused request gains another copy of every configured header on each round trip. It grows without bound until the server rejects it — a downstream report in Alloy (grafana/alloy#7016) shows ~1000 identical X-Api-Key lines in one request and scrapes failing with 431.

There is a second effect: Header.Set on the clone of a request built without a header panics with assignment to entry in nil map, because the shared nil map is never replaced.

Introduced in 56870db ("Modernize Go"), which replaced the manual copy loop:

-	r2.Header = make(http.Header)
-	for k, s := range r.Header {
-		r2.Header[k] = s
-	}
+	maps.Copy(r.Header, r2.Header)

The arguments are also the wrong way round, but swapping them is not enough — the clone needs its own map.

Fix in #982.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in config/http_config.go at cloneRequest and inspect the round trippers that clone and modify headers. Verify that cloned requests do not mutate the caller's headers, repeated round trips do not duplicate configured headers, and setting a header on a request without headers does not panic.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
networking
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
85/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.