Skip to content

Share one HTTP client and stop promcheck following redirects - #219

Merged
vertti merged 2 commits into
mainfrom
share-http-client
Aug 11, 2026
Merged

Share one HTTP client and stop promcheck following redirects#219
vertti merged 2 commits into
mainfrom
share-http-client

Conversation

@vertti

@vertti vertti commented Aug 11, 2026

Copy link
Copy Markdown
Owner

httpcheck and promcheck each defined their own HTTPClient and RealHTTPClient. The copies were identical except promcheck's never gained the CheckRedirect guard — so preflight prometheus followed 3xx responses anywhere, including to another host.

This is the clearest case in the review of duplication causing a security bug rather than merely being untidy, so removing the duplication is the fix.

The leak

Go strips Authorization and Cookie when a redirect crosses hosts, but not custom headers — and Mimir, Cortex, Thanos and Grafana Cloud carry tenancy in exactly those. Reproduced with a Prometheus that 302s to a different server:

X-Api-Key: SUPERSECRET      → arrived at the redirect destination
X-Scope-OrgID: tenant-42    → arrived too
[OK]                        → verdict came from the attacker's response body

So the destination both harvested the credentials and decided the check passed. promcheck has no --follow-redirects flag, so there was no way to opt out either.

Change

pkg/httpclient holds the single Client interface and Real implementation. Redirects are off unless FollowRedirects is set — what httpcheck already did, and promcheck did not. httpcheck's --follow-redirects still works as an explicit opt-in.

-40 lines pkg/httpcheck/check.go
-32 lines pkg/promcheck/check.go
+48 lines pkg/httpclient/client.go   (one definition)

InsecureSkipVerify now appears exactly once in non-test code, where it previously appeared twice with two separate //nolint:gosec justifications.

Tests

TestRealHTTPClient_DoesNotFollowRedirects was written first and confirmed red — it printed the leaked headers verbatim:

Expected nil, but got: http.Header{..., "X-Api-Key":[]string{"SUPERSECRET"},
                                       "X-Scope-Orgid":[]string{"tenant-42"}}

It asserts both that credentials don't reach the destination and that a 302 is not a passing verdict. The existing RealHTTPClient tests move to pkg/httpclient alongside the type — including the redirects-enabled case, so the opt-in path stays covered.

Suite green, go vet clean on linux/darwin/windows.

httpcheck and promcheck each defined HTTPClient and RealHTTPClient. The
copies were identical except promcheck's never gained the CheckRedirect
guard, so `preflight prometheus` followed 3xx anywhere — including to
another host.

Go strips Authorization and Cookie across hosts but not custom headers, and
Mimir, Cortex, Thanos and Grafana Cloud carry tenancy in exactly those.
Reproduced against a Prometheus that 302s elsewhere:

    X-Api-Key: SUPERSECRET   arrived at the redirect destination
    X-Scope-OrgID: tenant-42 arrived too
    [OK]                     verdict came from the attacker's response body

So the destination both harvested the credentials and decided the check
passed.

pkg/httpclient now holds the single Client interface and Real implementation
with redirects off unless FollowRedirects is set, which is what httpcheck
already did and promcheck did not. This is the duplication causing the bug,
so removing the duplication is the fix rather than a cleanup alongside it.

The RealHTTPClient tests move to pkg/httpclient, where the type now lives.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@vertti, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3cb8d2c0-3de4-4274-ade3-cf5b962c52e1

📥 Commits

Reviewing files that changed from the base of the PR and between 9b003da and 4f9994d.

📒 Files selected for processing (9)
  • cmd/preflight/cmd_http.go
  • cmd/preflight/cmd_prometheus.go
  • integration_test.go
  • pkg/httpcheck/check.go
  • pkg/httpcheck/check_test.go
  • pkg/httpclient/client.go
  • pkg/httpclient/client_test.go
  • pkg/promcheck/check.go
  • pkg/promcheck/check_test.go

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.33333% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 93.19%. Comparing base (9b003da) to head (4f9994d).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/promcheck/check.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #219      +/-   ##
==========================================
+ Coverage   93.11%   93.19%   +0.07%     
==========================================
  Files          49       50       +1     
  Lines        1873     1865       -8     
==========================================
- Hits         1744     1738       -6     
+ Misses         93       92       -1     
+ Partials       36       35       -1     
Files with missing lines Coverage Δ
cmd/preflight/cmd_http.go 100.00% <100.00%> (ø)
cmd/preflight/cmd_prometheus.go 100.00% <100.00%> (ø)
pkg/httpcheck/check.go 93.45% <100.00%> (-0.61%) ⬇️
pkg/httpclient/client.go 100.00% <100.00%> (ø)
pkg/promcheck/check.go 93.91% <0.00%> (+1.23%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@vertti
vertti merged commit b9cdca9 into main Aug 11, 2026
17 checks passed
@vertti
vertti deleted the share-http-client branch August 11, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant