Introduction
The go.mod file in any Go project is the authoritative list of what your application trusts. When one of those trusted dependencies has a security flaw, every application that pulls it in inherits the risk—silently, and often without any obvious code change on your part.
That's exactly what happened with CVE-2026-42151: a high-severity information disclosure vulnerability in github.com/prometheus/prometheus that caused Azure OAuth client secrets to be exposed in plaintext through the Prometheus configuration API. Any application embedding Prometheus and exposing its config endpoint—even internally—was potentially leaking cloud credentials to anyone who could reach that endpoint.
The fix was a single line change in go.mod:
- github.com/prometheus/prometheus v0.310.0
+ github.com/prometheus/prometheus v0.311.3
But understanding why this line matters requires understanding how Prometheus handles Azure OAuth configuration, what the config API exposes, and why credential redaction is a security requirement, not just a nice-to-have.
The Vulnerability Explained
What the Prometheus Config API Does
Prometheus exposes a /api/v1/status/config HTTP endpoint that returns the currently loaded configuration in YAML format. This is genuinely useful for operators: it lets you inspect the running configuration without needing filesystem access to the server. However, this convenience becomes a critical security hole when the configuration contains secrets.
Azure OAuth in Prometheus
Prometheus supports scraping metrics from Azure Monitor using an OAuth2 client credentials flow. The configuration for this looks something like:
azure_sd_configs:
- environment: AzurePublicCloud
authentication_method: OAuth
subscription_id: "your-subscription-id"
tenant_id: "your-tenant-id"
client_id: "your-client-id"
client_secret: "your-super-secret-value" # ← THIS is the problem
In versions prior to v0.311.3 (including v0.310.0), when the config API serialized this configuration struct back to YAML for the API response, the client_secret field was included verbatim. There was no redaction step that replaced the secret value with a placeholder like <secret> before returning the response.
The Attack Scenario
Consider a real-world scenario: a platform engineering team runs Prometheus inside a Kubernetes cluster to monitor Azure-hosted workloads. They've configured Azure service discovery using an OAuth client secret that has Reader permissions on their Azure subscription.
An attacker who gains access to the internal network—through a compromised pod, a misconfigured ingress, or a lateral movement step—can simply call:
GET http://prometheus-server:9090/api/v1/status/config
The response includes the full Prometheus configuration in YAML, including the client_secret in plaintext. The attacker now has valid Azure OAuth credentials and can enumerate Azure resources, access storage accounts, or escalate privileges depending on what that service principal can access.
No authentication bypass is needed. No memory corruption. Just a single HTTP GET to a monitoring endpoint that was never supposed to be a credential vault.
Why This Affects Your Go Application
If your Go application embeds Prometheus (as many observability platforms, SLO tools, and monitoring agents do), and it exposes the Prometheus config API, it inherited this vulnerability through its go.mod dependency on github.com/prometheus/prometheus v0.310.0. The vulnerability lives entirely within the Prometheus library code—your application code didn't need to do anything wrong.
The Fix
What Changed in go.mod
The fix is a version bump in two files:
go.mod — the dependency declaration:
- github.com/prometheus/prometheus v0.310.0
+ github.com/prometheus/prometheus v0.311.3
go.sum — the cryptographic integrity hashes for the new version (updated automatically by go mod tidy).
The go.sum changes also reflect updated transitive dependencies pulled in by the new Prometheus version, including:
+cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM=
+github.com/aws/aws-sdk-go-v2 v1.41.4 h1:10f50G7WyU02T56ox1wWXq+zTX9I1zxG46HYuG1hH/k=
+github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0=
These transitive updates are part of Prometheus v0.311.3's dependency tree and are verified by the hash entries in go.sum.
What Prometheus v0.311.3 Actually Fixed
The core fix in Prometheus v0.311.3 is in the Azure service discovery configuration struct. The client_secret field (and similar credential fields) are now redacted before serialization when the config API marshals the configuration to YAML.
The pattern before the fix effectively allowed:
// Simplified representation of the vulnerable behavior
type AzureSDConfig struct {
ClientID string `yaml:"client_id"`
ClientSecret string `yaml:"client_secret"` // serialized as-is
TenantID string `yaml:"tenant_id"`
}
After the fix, sensitive fields use Prometheus's config.Secret type (or equivalent redaction mechanism), which implements a custom YAML marshaler that outputs <secret> instead of the actual value:
// Simplified representation of the fixed behavior
type AzureSDConfig struct {
ClientID string `yaml:"client_id"`
ClientSecret config.Secret `yaml:"client_secret"` // marshals as "<secret>"
TenantID string `yaml:"tenant_id"`
}
This means the config API can still be used for debugging and operational visibility—it just no longer leaks the actual secret values.
Why Both go.mod and go.sum Must Change
A common misconception is that only go.mod matters. In practice, go.sum is the security layer: it contains the expected cryptographic hashes of every module version your build depends on. If go.sum doesn't contain the hash for the new version, go build will refuse to proceed. Both files must be updated together for the fix to be complete and verifiable.
Prevention & Best Practices
1. Treat Dependency Upgrades as Security Patches
CVE-2026-42151 required zero changes to application code—just a dependency version bump. This is increasingly common in the Go ecosystem. Establish a process for regularly reviewing and applying security updates to dependencies, not just your own code.
2. Use govulncheck in Your CI Pipeline
Google's govulncheck tool scans your Go module graph against the Go vulnerability database and reports only vulnerabilities that affect code paths actually called by your application:
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
This would have flagged CVE-2026-42151 before it reached production.
3. Run Trivy on Your Container Images and Source Code
Trivy (the scanner that detected this vulnerability) can scan go.mod files directly:
trivy fs --scanners vuln .
Integrate this into your CI/CD pipeline to catch vulnerable dependencies before deployment.
4. Never Expose Monitoring Endpoints Without Authentication
Even with the fix applied, the Prometheus config API should be protected:
- Use network policies to restrict access to monitoring ports
- Place Prometheus behind an authenticating reverse proxy
- Consider using --web.config.file to enable TLS and basic auth on the Prometheus HTTP server
5. Audit Configuration Structs for Credential Leakage
If you build Go applications that serialize configuration to APIs or logs, audit every struct that might contain secrets. Use types that implement custom marshalers to redact sensitive values:
type Secret string
func (s Secret) MarshalYAML() (interface{}, error) {
if s != "" {
return "<secret>", nil
}
return "", nil
}
This pattern is exactly what Prometheus v0.311.3 uses to fix the vulnerability.
Relevant Standards
- CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
- OWASP A02:2021: Cryptographic Failures (which includes storing/transmitting secrets in plaintext)
- OWASP API Security Top 10: API3:2023 - Broken Object Property Level Authorization (over-exposure of object properties)
Key Takeaways
- The Prometheus config API in v0.310.0 serialized
client_secretfields from Azure OAuth configurations without any redaction, making them readable to anyone who could reach the endpoint. - A single line change in
go.mod— upgrading fromv0.310.0tov0.311.3— is sufficient to remediate this vulnerability in any Go application using this dependency. go.summust be updated alongsidego.mod: the hash entries forgithub.com/prometheus/prometheus v0.311.3and its updated transitive dependencies (includingaws-sdk-go-v2 v1.41.4) must be present for the build to succeed.- Monitoring infrastructure is a high-value target: Prometheus, Grafana, and similar tools often hold credentials for every system they monitor. Their APIs deserve the same access controls as production services.
- Credential redaction at the serialization layer is the correct fix: restricting API access reduces exposure but doesn't eliminate the root cause. The secret should never appear in the API response at all.
How Orbis AppSec Detected This
- Source: The
client_secretfield in Azure OAuth service discovery configuration, supplied by operators via Prometheus configuration files and stored in theAzureSDConfigstruct. - Sink: The Prometheus
/api/v1/status/configHTTP endpoint, which marshaled the full configuration struct—including unredacted credential fields—into a YAML API response. - Missing control: No redaction or masking of the
client_secretfield prior to YAML serialization in the config API handler. The field used a plainstringtype rather than aconfig.Secrettype with a custom marshaler. - CWE: CWE-200 — Exposure of Sensitive Information to an Unauthorized Actor.
- Fix: Upgraded
github.com/prometheus/prometheusfromv0.310.0tov0.311.3ingo.mod, which includes the upstream patch that redacts credential fields before config API serialization.
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
CVE-2026-42151 is a reminder that security vulnerabilities don't always look like buffer overflows or SQL injections. Sometimes they're a missing redaction step in a monitoring tool's API response—quiet, hard to spot in a code review, but potentially catastrophic when Azure credentials end up in the wrong hands.
The fix is straightforward: upgrade github.com/prometheus/prometheus to v0.311.3 in your go.mod. But the broader lesson is about the security posture of your entire dependency graph. Every library you import is code you're responsible for. Automated scanning tools like Trivy and govulncheck, combined with automated remediation workflows, are no longer optional—they're the baseline for responsible Go development.
If you're running Prometheus with Azure service discovery, audit your config API exposure today, apply this upgrade, and consider rotating any Azure OAuth client secrets that may have been exposed.
References
- CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
- OWASP API Security Top 10 - API3:2023 Broken Object Property Level Authorization
- OWASP Secrets Management Cheat Sheet
- Go Vulnerability Database - govulncheck
- Trivy Vulnerability Scanner Documentation
- Semgrep rules for Go credential exposure
- fix: upgrade github.com/prometheus/prometheus to 0.311.3 (CVE-2026-42151)