Skip to content

Conversation

@bradlarsen
Copy link
Contributor

This PR updates the JWT detector to more simply and more robustly prevent making requests to local IPs.

The previous implementation did its checking at the hostname level, but this approach doesn't work in general when redirects are involved. The new implementation has less code and does its checking at the HTTP transport level, after DNS resolution.

@bradlarsen bradlarsen requested a review from a team December 17, 2025 19:14
@bradlarsen bradlarsen requested a review from a team as a code owner December 17, 2025 19:14
Copy link
Contributor

@shahzadhaider1 shahzadhaider1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving to unblock. This looks good from a security standpoint, and I agree with using the detector HTTP client here.

One thing I hope we have considered: switching from common.SaneHttpClient means we lose the retry/instrumentation layer (metrics we currently export to Prometheus/Grafana).

Copy link
Contributor

@rosecodym rosecodym left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the code consolidation but I think it's a bummer that this costs us some instrumentation. Did you look into whether we can get that easily as well? (If we can't, don't worry about it.)

I believe this PR does introduce a data race, though.

Comment on lines +81 to +84
if client == nil {
// Use a client that disallows accessing local IPs.
// This avoids a potential blind SSRF.
client = detectors.NewDetectorHttpClient(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FromData can be called concurrently from multiple goroutines, so I believe this read/write needs some sort of synchronization. (My understanding is that this precise pattern generally works in the current version of Go but is technically disallowed by the spec, and I'd prefer to play it safe.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes! Good to know; thanks for the pointer.

type Scanner struct {
client *http.Client
}
type Scanner struct{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC the primary motivation for putting client inside the struct is test mocking. I don't know whether that still stands.

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.

5 participants