ZeroPath at Black Hat USA 2026

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

A brief summary of CVE-2026-44902, a high severity denial of service in the OpenTelemetry JS Prometheus exporter where a single malformed HTTP request crashes the entire Node.js process. Includes proof of concept details, patch analysis, and 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. With OpenTelemetry having just graduated from the CNCF on May 21, 2026, as the second most active project after Kubernetes (over 15,000 contributors from 1,800+ organizations), the blast radius of CVE-2026-44902 extends across a significant portion of the cloud native ecosystem.

The vulnerability is a textbook missing error handler: the Prometheus exporter's HTTP server parses incoming request URLs using JavaScript's URL constructor without a try...catch block. 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 the fact that this is remotely exploitable, requires 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 determine if it matches the configured metrics endpoint path. The vulnerable code performed this parsing inline within a conditional expression:

// 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 protect against syntactically invalid URLs. This is where Node.js's HTTP parser behavior becomes relevant: 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 a TypeError: Invalid URL.

Because there is no try...catch wrapping this call, the TypeError propagates up the call stack as an uncaught exception. In Node.js, an uncaught exception triggers the default behavior of printing the stack trace and terminating the process with a non zero exit code. The entire application dies, not just the metrics serving component.

This is classified as CWE-755: Improper Handling of Exceptional Conditions, an abstract weakness that manifests 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 straightforward:

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

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

  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 pod scheduling and termination cycles. The loss of the metrics endpoint also blinds monitoring systems, potentially masking other malicious activity.

Default Binding Amplifies Exposure

The exporter binds to 0.0.0.0:9464 by default, which means 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 has identified approximately 336,000 internet facing Prometheus servers and exporters, including roughly 296,000 exporters exposed to the public internet. While that figure covers all Prometheus infrastructure and not just OpenTelemetry JS instances specifically, it illustrates 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 special attention because it is commonly used for zero code instrumentation. Organizations may be running the vulnerable Prometheus exporter without being explicitly aware of it, since the package automatically configures exporters 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 the following unhandled exception:
TypeError: Invalid URL
    at new URL (...)
    at PrometheusExporter._requestHandler (...)

The key insight is that Node.js's built in HTTP parser accepts absolute form URIs (like http://) for HTTP proxy compatibility. The string "http://" is a valid value for request.url from the parser's perspective, but it is not a valid URL from the URL constructor's perspective. This mismatch between what the HTTP parser accepts and what the URL parser rejects is the gap the vulnerability exploits.

No special tools, exploit kits, or authentication are required. A single unauthenticated network packet is sufficient for 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 restructures the logic by extracting the URL parsing into its own try...catch block, cleanly 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 entire process, the catch block intercepts it, sets the HTTP response status code to 400 (Bad Request), writes a 'Bad Request' body, and returns early. The Node.js process remains fully intact and continues 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 versions prior to these are affected. The vulnerability existed from the very first version of the exporter. The relevant commit is e8f439a.

Affected Systems and Versions

The following 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 that runs the OpenTelemetry Prometheus exporter's built in HTTP server. The default configuration binds to 0.0.0.0:9464, but any custom host/port configuration is equally vulnerable since 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 explicitly states that "the OpenTelemetry community has addressed 12 CVEs since GA." Recent CVEs across the project reveal 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

The recurrence of DoS vulnerabilities across multiple language SDKs (JavaScript, .NET) suggests a systemic issue with error handling and input validation in OpenTelemetry exporter implementations. The CWE-755 classification of CVE-2026-44902 reinforces this: improper handling of exceptional conditions is a pattern that can manifest wherever error handling is incomplete. Organizations relying on OpenTelemetry should consider auditing all HTTP facing OpenTelemetry components for similar patterns and applying 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
  • Jira
  • Linear
  • Slack
  • Security Compass
Security magnifying glass visualization