Automated Threat Modeling

OpenTelemetry JS Prometheus Exporter CVE-2026-44902: One Malformed Request Crashes Your Node.js Process (PoC and Patch Analysis)

CVE-2026-44902 is a high severity denial of service in the OpenTelemetry JS Prometheus exporter, where a single malformed HTTP request crashes the entire Node.js process. This post covers the proof of concept, the patch, and the affected package versions.

CVE Analysis

10 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-05-27

OpenTelemetry JS Prometheus Exporter CVE-2026-44902: One Malformed Request Crashes Your Node.js Process (PoC and Patch Analysis)
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A single malformed HTTP request can terminate any Node.js process running the OpenTelemetry JavaScript Prometheus exporter, taking down not just the metrics endpoint but the entire application. OpenTelemetry graduated from the CNCF on May 21, 2026, as the second most active project after Kubernetes, with over 15,000 contributors from more than 1,800 organizations. That reach is what makes CVE-2026-44902 matter: the blast radius extends across a large part of the cloud native ecosystem.

The vulnerability is a missing error handler. The Prometheus exporter's HTTP server parses incoming request URLs with JavaScript's URL constructor and does not wrap the call in a try...catch. When a request arrives with an invalid URI, the resulting TypeError propagates as an uncaught exception and kills the process. The CVSS 3.1 score of 7.5 (HIGH) reflects that it is remotely exploitable, needs no authentication, and causes complete loss of availability.

Technical Information

Root Cause: Unhandled TypeError in URL Parsing

The vulnerability lives in the _requestHandler method of PrometheusExporter.ts. The exporter's built-in HTTP server (bound to 0.0.0.0:9464 by default) processes incoming requests by parsing the request URL to check whether it matches the configured metrics endpoint path. The vulnerable code did this parsing inline, inside a conditional:

// BEFORE (vulnerable) if ( request.url != null && new URL(request.url, this._baseUrl).pathname === this._endpoint ) { this._exportMetrics(response); } else { this._notFound(response); }

The request.url != null check guards against null or undefined values, but it does not catch syntactically invalid URLs. This is where Node.js's HTTP parser behavior comes in: it accepts absolute-form URIs for HTTP proxy compatibility. When a client sends a request line like GET http:// HTTP/1.1, Node.js sets request.url to the string "http://". That string passes the null check, but when passed to the URL constructor it throws TypeError: Invalid URL.

Because nothing wraps the call in a try...catch, the TypeError propagates up the call stack as an uncaught exception. In Node.js, an uncaught exception prints the stack trace and terminates the process with a non-zero exit code. The entire application dies, not just the metrics component.

This is classified as CWE-755: Improper Handling of Exceptional Conditions, an abstract weakness that shows up wherever error handling is incomplete around operations that can throw.

CVSS Vector Breakdown

The CVSS v3.1 vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H breaks down as follows:

ComponentValueMeaning
Attack Vector (AV)NetworkExploitable remotely
Attack Complexity (AC)LowNo special conditions required
Privileges Required (PR)NoneNo authentication needed
User Interaction (UI)NoneNo user action needed
Scope (S)UnchangedImpact limited to the vulnerable component
Confidentiality (C)NoneNo information disclosure
Integrity (I)NoneNo data modification
Availability (A)HighComplete loss of availability

Attack Flow

The exploitation path is short:

  1. Identify the target. The attacker finds a Node.js service exposing the OpenTelemetry Prometheus metrics endpoint. The default configuration binds to 0.0.0.0:9464, so the endpoint is reachable on all network interfaces unless explicitly restricted.

  2. Send a malformed request. The attacker sends a single HTTP request with an invalid absolute-form URI. The request line GET http:// HTTP/1.1 is enough.

  3. Process termination. Node.js's HTTP parser accepts the request and sets request.url to "http://". The URL constructor throws a TypeError. The unhandled exception terminates the process.

  4. Cascading impact. In Kubernetes environments, the pod restarts. Repeated attacks can trigger CrashLoopBackOff conditions, degrading cluster performance through repeated scheduling and termination cycles. Losing the metrics endpoint also blinds monitoring systems, which can mask other malicious activity.

Default Binding Amplifies Exposure

The exporter binds to 0.0.0.0:9464 by default, so it listens on all network interfaces. Services deployed without explicit host binding restrictions expose the metrics endpoint to any network the host is connected to. Aqua Security research identified roughly 336,000 internet-facing Prometheus servers and exporters, including about 296,000 exporters exposed to the public internet. That figure covers all Prometheus infrastructure, not just OpenTelemetry JS instances, but it shows the scale of exposed telemetry endpoints.

Three Packages Affected

The vulnerability is not limited to the direct exporter package. Three npm packages carry the vulnerable code path:

PackageHow It Is Affected
@opentelemetry/exporter-prometheusDirect use via its built-in HTTP server
@opentelemetry/sdk-nodeWhen OTEL_METRICS_EXPORTER includes prometheus
@opentelemetry/auto-instrumentations-nodeWhen loaded via --require or --import with Prometheus as the metrics exporter

The @opentelemetry/auto-instrumentations-node package deserves attention because it is commonly used for zero-code instrumentation. Organizations may be running the vulnerable Prometheus exporter without knowing it, since the package configures exporters automatically based on environment variables.

Proof of Concept

A public proof of concept is documented directly in the official GitHub Security Advisory (GHSA-q7rr-3cgh-j5r3), published by the OpenTelemetry JS maintainers on May 6, 2026.

Reproduction steps:

  1. Start any Node.js application with the OpenTelemetry Prometheus exporter running on the default port 9464.

  2. From any host that can reach the metrics port, send a single raw TCP packet containing a malformed HTTP request:

echo -ne 'GET http:// HTTP/1.1\r\nHost: localhost\r\n\r\n' | nc localhost 9464
  1. The target Node.js process crashes immediately with this unhandled exception:
TypeError: Invalid URL
    at new URL (...)
    at PrometheusExporter._requestHandler (...)

The mechanism is the gap between two parsers. Node.js's built-in HTTP parser accepts absolute-form URIs like http:// for HTTP proxy compatibility, so the string "http://" is a valid value for request.url from its perspective. The URL constructor rejects that same string. The vulnerability exploits the mismatch between what the HTTP parser accepts and what the URL parser rejects.

No special tools, exploit kits, or authentication are required. A single unauthenticated network packet causes complete denial of service.

Patch Information

The OpenTelemetry maintainers addressed CVE-2026-44902 through Pull Request #6674, authored by @arminru (porting an original fix by @homanp). The PR was merged on May 6, 2026, by @pichlermarc and shipped in the experimental/v0.217.0 release the same day. The change touches a single file, PrometheusExporter.ts, with 11 additions and 4 deletions.

The patch extracts the URL parsing into its own try...catch block, separating the error-prone operation from the routing decision:

// AFTER (patched) let pathname: string | undefined; try { if (request.url != null) { pathname = new URL(request.url, this._baseUrl).pathname; } } catch { response.statusCode = 400; response.end('Bad Request'); return; } if (pathname === this._endpoint) { this._exportMetrics(response); } else { this._notFound(response); }

Instead of letting the TypeError crash the process, the catch block intercepts it, sets the response status code to 400 (Bad Request), writes a 'Bad Request' body, and returns early. The Node.js process stays intact and keeps serving legitimate Prometheus scrape requests.

Fixed package versions:

PackageFixed Version
@opentelemetry/exporter-prometheus0.217.0
@opentelemetry/sdk-node0.217.0
@opentelemetry/auto-instrumentations-node0.75.0

All earlier versions are affected. The vulnerability existed from the first version of the exporter. The relevant commit is e8f439a.

Affected Systems and Versions

These npm packages are vulnerable in all versions prior to the specified fixed version:

  • @opentelemetry/exporter-prometheus: all versions before 0.217.0
  • @opentelemetry/sdk-node: all versions before 0.217.0 (when OTEL_METRICS_EXPORTER includes prometheus)
  • @opentelemetry/auto-instrumentations-node: all versions before 0.75.0 (when loaded with Prometheus as the metrics exporter via --require or --import)

The vulnerable configuration is any Node.js application running the OpenTelemetry Prometheus exporter's built-in HTTP server. The default configuration binds to 0.0.0.0:9464, but any custom host or port is equally vulnerable, because the root cause is in the request handler, not the binding configuration.

Vendor Security History

OpenTelemetry has a documented track record of vulnerability response. The CNCF graduation announcement states that "the OpenTelemetry community has addressed 12 CVEs since GA." Recent CVEs across the project show a pattern of denial of service vulnerabilities in exporter implementations:

CVE IDComponentDescriptionSeverity
CVE-2026-44902opentelemetry-js (Prometheus exporter)Process crash via malformed HTTP request7.5 (High)
CVE-2026-40891opentelemetry-dotnet (gRPC exporter)DoS via unbounded grpc-status-details-bin header parsingHigh
CVE-2026-24051opentelemetry-goPath Hijacking (Untrusted Search Paths) on macOS/DarwinAssigned

DoS vulnerabilities recur across multiple language SDKs, in JavaScript and .NET, which points to a systemic issue with error handling and input validation in OpenTelemetry exporter implementations. The CWE-755 classification of CVE-2026-44902 fits that reading: improper handling of exceptional conditions can appear wherever error handling is incomplete. Organizations relying on OpenTelemetry should audit all HTTP-facing OpenTelemetry components for similar patterns and apply defense in depth beyond individual patches.

The project maintains a published security policy on GitHub and coordinates vulnerability disclosure through GitHub Security Advisories.

References

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Gerrit
  • CVS
  • Jira
  • Linear
  • Slack
  • Security Compass
Explore integrations
Security magnifying glass visualization