Microsoft’s security response center last week flagged a high-severity denial-of-service vulnerability in the OpenTelemetry Go instrumentation libraries that could let an attacker crash your service with nothing more than a few hundred well-crafted HTTP requests. Tracked as CVE-2023-45142, the flaw allows unbounded memory growth inside the metrics pipeline by injecting ever-changing HTTP header values—and it is fixed in the 0.44.0 release of the OpenTelemetry Go Contrib modules.
The vulnerability is a label explosion
When you add OpenTelemetry’s otelhttp handler to a Go HTTP server, the library automatically records common request attributes like the HTTP method and the User-Agent string as metric labels. That decision is normally helpful: you get dashboards broken down by method (GET, POST, PUT) and can spot anomalies based on client headers. But the early implementations recorded every distinct value without a ceiling. If an attacker crafts requests with random or deliberately malformed method tokens (“PATCH” one second, “EXPLODE” the next) or a unique User-Agent per request, the metrics storage layer must allocate a new label set for every variation.
Memory that should be tracking a handful of stable dimensions suddenly balloons. Because the standard OTel Go SDK keeps in-process state for metric labels and exporters often maintain their own registries, each novel label combination eats another slice of heap. After enough requests—easily generated from a simple script or a single curl loop—the process runs out of memory, killing availability (SIGKILL in containerized environments) or degrading performance to the point where legitimate traffic gets starved.
The CVSS v3.1 score of 7.5 reflects that the attack works remotely, needs no authentication, and can cause sustained or persistent denial of service. While the CVE does not grant code execution or exfiltration, for any public-facing Go service it represents a simple, scriptable way to bring down an endpoint.
Affected components and how the fix stops the madness
The vulnerability lives inside the go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp package and any framework adapters that wrap it. According to the OpenTelemetry maintainers’ advisory, the following modules were vulnerable before version 0.44.0:
otelhttp(the core HTTP wrapper)otelrestful(go-restful)otelgin(Gin)otelmux(Gorilla Mux)otelecho(Echo)otelmacaron(Macaron)otelhttptrace
All of these shared a common code path that called httpconv.ServerRequest to produce http.method and http.user_agent labels without cardinality bounds.
The 0.44.0 release introduces two key changes:
- Method whitelisting. Instead of recording every requested method string verbatim, the instrumentation maps methods to a small, predefined set of well-known values (GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH, CONNECT, TRACE). Anything unrecognized is collapsed into a generic bucket like
_OTHER, preventing an attacker from generating thousands of unique entries. - User-Agent removal. The
http.user_agentlabel is no longer collected by default. It was the other major high-cardinality vector, since clients routinely send different User-Agent strings and an adversary can randomize them endlessly. If an operator still needs User-Agent data for analytics, it can be captured as a log attribute or re-enabled through configuration—but only after understanding the risk.
These changes bring the instrumentation in line with the cardinality-engineering rule: metrics labels must be bounded.
What it means for your team
The impact travels in two directions: for developers building Go services and for the operators who keep those services alive.
For developers and platform engineers
If you or your team has added OpenTelemetry instrumentation to a Go service—whether directly or through a framework, an API gateway, or a vendor library—chances are high that you were pulling in a vulnerable version of otelhttp without knowing it. The fix is a library upgrade, not a configuration change. That means every build that references go.opentelemetry.io/contrib must be updated. Even if your application code never directly imports otelhttp, a transitive dependency might. Check your go.sum or your SBOM (software bill of materials) for any line matching go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp; if the version is earlier than v0.44.0, you are exposed.
Knock-on effects matter: changing metric labels can alter dashboards, alerts, and historical time series. The removal of http.user_agent means any panel that grouped by that label will stop receiving data. The whitelisting of methods might slightly change cardinality patterns. After the upgrade, validate your monitoring stack and tune any queries that expected the old labels.
For SREs, DevOps, and security teams
Even if you cannot immediately rebuild and deploy the patch, you can blunt the attack. Filters, load-balancer rules, and WAF policies that reject requests with nonstandard methods (anything beyond the nine common ones) or excessively long method strings will neuter the most obvious exploitation path. Rate-limiting public endpoints also raises the bar, though a determined attacker can still drip-feed requests over hours.
The most reliable short-term defense inside the application is to use otelhttp.WithFilter(). This function lets you inspect each incoming request and decide whether to record metrics for it. A filter that drops metrics when the HTTP method is unrecognized or the User-Agent appears suspicious provides a surgical fix. Combine that with hard memory limits on your containers so that a gradual leak cannot take down a shared node.
Finally, treat your metrics pipeline as a security surface. Watch for spikes in label cardinality—an order-of-magnitude jump in the number of unique dimension values for any metric is a red flag. Many monitoring backends (Prometheus, Grafana Mimir, Datadog) support cardinality alerts; turn them on for the metrics that Otel produces.
How we ended up with explosive labels
The root cause isn’t a simple coding mistake. It’s a tension between observability’s natural desire to collect everything and production engineering’s requirement to stay stable. When the OpenTelemetry Go Contrib library was first designed, the team made the product-friendly choice of recording every attribute that developers and operators might want. The http.method label seemed harmless—how many HTTP methods exist? And http.user_agent, while clearly higher cardinality, was a common ask for analyzing client types. The library left filtering and bounding to the operator.
In retrospect, that was too optimistic. A public-facing microservice sees traffic from many legitimate clients, synthetic bots, and curiosity-driven scripters, let alone malicious actors. Once security researchers demonstrated that you could deliberately exhaust memory by injecting unique headers, the maintainers moved quickly. The 0.44.0 release reflects a more defensive posture that many observability projects are now adopting: default to safe, low-cardinality labels and require explicit opt-in for anything that could explode.
Microsoft’s advisory elevated the issue to a CVE, which in turn prompted enterprise vendors (whose products often bundle OpenTelemetry) to issue their own bulletins. This ripple effect is a healthy part of modern supply-chain security: vulnerabilities in common libraries get tracked, patched, and communicated across the ecosystem.
What to do now
Across all audiences, three actions matter most:
- Upgrade to version 0.44.0 or later of all affected Go Contrib modules. Pin your
go.modto the fixed release and rungo mod tidy. If you use vendoring, update the vendor directory. This is the only change that eliminates the vulnerability at its source. - If you can’t upgrade immediately, apply a filter. Use
otelhttp.WithFilter()to reject metrics from requests that don’t use standard HTTP methods or that carry unnaturally long method tokens. Here is a minimal example:
handler := otelhttp.NewHandler(myHandler, "server",
otelhttp.WithFilter(func(r *http.Request) bool {
method := r.Method
allowed := map[string]bool{"GET": true, "POST": true, "PUT": true, "DELETE": true, "HEAD": true, "OPTIONS": true, "PATCH": true}
return allowed[method]
}),
)
- Add cardinality monitoring. If your metrics system allows it, set hard limits on the number of unique label values per metric. Even with the fix, a future library change or a different instrumentation could introduce similar risks. Alert on rapid growth in distinct label sets.
For teams responsible for many services, the checklist expands:
- Run an automated scan of all Go modules across your estate for
go.opentelemetry.io/contribversions below 0.44.0. - Update any CI pipelines that enforce dependency policies to reject the vulnerable range.
- Coordinate with platform or distribution vendors who supply OpenTelemetry as part of a larger product; they may issue their own patches.
- After upgrading, test dashboards and check for
nilvalues wherehttp.user_agentlabels used to populate panels.
Don’t let observability become a weapon
CVE-2023-45142 is not the first cardinality-explosion DoS, and it won’t be the last. As telemetry becomes a universal layer inside every service, the boundary between “monitoring” and “surface area for abuse” blurs. The healthy push to make instrumentation automatic must be balanced with safe defaults. The 0.44.0 fix gets that balance right by whitelisting methods and pulling back on user‑supplied labels. But the real guardrail is cultural: treat your metric labels like a database schema—plan for what you’ll store, set bounds, and never let an external input dictate unlimited growth.
For now, OpenTelemetry users should grab the patch, verify their sandbox environments, and then push to production. The few minutes it takes to bump a Go dependency could save hours of debugging a mysteriously OOM‑killed container at 3 a.m.