Back to Blog
high SEVERITY9 min read

How Denial of Service via malformed HTTP header decoding happens in Node.js @opentelemetry/propagator-jaeger and how to fix it

CVE-2026-59892 is a high-severity Denial of Service vulnerability in `@opentelemetry/propagator-jaeger` versions prior to 2.9.0, where malformed HTTP trace-context headers could cause the propagator's decoding logic to crash a Node.js application. The fix upgrades the package from 2.8.0 to 2.9.0, patching the unsafe header parsing behavior and eliminating the attack surface for any service that propagates distributed tracing headers.

O
By Orbis AppSec
Published July 30, 2026Reviewed July 30, 2026

Answer Summary

CVE-2026-59892 is a Denial of Service (CWE-400) vulnerability in the `@opentelemetry/propagator-jaeger` npm package (Node.js) affecting version 2.8.0 and earlier. Attackers can craft malformed Jaeger HTTP trace-context headers that cause the propagator's decoding logic to throw an unhandled error, crashing or hanging the receiving service. The fix is to upgrade `@opentelemetry/propagator-jaeger` from 2.8.0 to 2.9.0 (and its internal dependency `@opentelemetry/core` from 2.8.0 to 2.9.0), which hardens the header-parsing code against malformed input.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade `@opentelemetry/propagator-jaeger` to 2.9.0, which includes hardened header-decoding logic in the updated `@opentelemetry/core` 2.9.0 dependency
riskAttackers can crash or hang any Node.js service that uses Jaeger trace-context propagation by sending a single malformed HTTP header
languageJavaScript / Node.js
root cause`@opentelemetry/propagator-jaeger` 2.8.0 did not safely validate/parse incoming Jaeger trace headers before processing them, allowing malformed input to trigger an unhandled error
vulnerabilityDenial of Service via malformed HTTP header decoding

How Denial of Service via malformed HTTP header decoding happens in Node.js @opentelemetry/propagator-jaeger and how to fix it


The Vulnerability at a Glance

Field Detail
Vulnerability Denial of Service via malformed HTTP header decoding
CWE CWE-400 — Uncontrolled Resource Consumption
Language JavaScript / Node.js
Risk Single malformed HTTP request can crash a production service
Root Cause @opentelemetry/propagator-jaeger 2.8.0 unsafely decodes Jaeger trace headers
Fix Upgrade to @opentelemetry/propagator-jaeger 2.9.0

Quick Answer

CVE-2026-59892 is a high-severity Denial of Service vulnerability in @opentelemetry/propagator-jaeger (Node.js) affecting version 2.8.0 and earlier. An attacker can send a single HTTP request containing a malformed Jaeger trace-context header, causing the propagator's decoding logic to throw an unhandled error and crash the receiving service. The fix is to upgrade the package to 2.9.0, which ships hardened header-parsing logic via an updated @opentelemetry/core 2.9.0 dependency.


Introduction

The package-lock.json file in this production Node.js application locked @opentelemetry/propagator-jaeger at version 2.8.0—a version containing a flaw in its HTTP header decoding path. That flaw, now tracked as CVE-2026-59892, means that any HTTP request arriving at a service endpoint that uses Jaeger trace-context propagation could be weaponized to take the service offline, simply by crafting a malformed value for the uber-trace-id header.

For developers building distributed systems with OpenTelemetry, this is a particularly insidious class of vulnerability: the attack surface isn't your business logic—it's the observability infrastructure sitting invisibly in every request's hot path.


The Vulnerability Explained

What is @opentelemetry/propagator-jaeger doing?

In a distributed tracing setup, the Jaeger propagator is responsible for extracting trace context from incoming HTTP headers and injecting it into outgoing ones. On every inbound HTTP request, the propagator reads the uber-trace-id header (Jaeger's native format), decodes it, and reconstructs a SpanContext object so that the current service's spans can be linked to the originating trace.

The header format looks like this:

uber-trace-id: {traceId}:{spanId}:{parentSpanId}:{flags}

For example:

uber-trace-id: 4bf92f3577b34da6a3ce929d0e0e4736:00f067aa0ba902b7:0:1

The propagator in version 2.8.0 splits this string by : and processes each segment. The vulnerability lies in what happens when the input doesn't conform to this format—or when it contains values specifically designed to trigger edge cases in the parsing logic (e.g., excessively long segments, non-hex characters in positions that assume hex, or Unicode sequences that cause string operations to behave unexpectedly).

The vulnerable dependency chain

Before the fix, package-lock.json resolved the package like this:

"node_modules/@opentelemetry/propagator-jaeger": {
  "version": "2.8.0",
  "license": "Apache-2.0",
  "dependencies": {
    "@opentelemetry/core": "2.8.0"
  }
}

The propagator delegates significant parsing work to @opentelemetry/core 2.8.0. The vulnerability exists at this layer: the core library's utility functions used to decode trace and span IDs from the header string did not adequately guard against malformed input, meaning a bad actor could trigger an unhandled exception that propagates up through the request handler.

How an attacker exploits this

The attack requires no authentication, no special privileges, and no knowledge of the application's internals. An attacker simply sends an HTTP request with a crafted uber-trace-id header to any endpoint of the target service:

curl -H "uber-trace-id: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:::::::::::::" \
     https://your-service.example.com/api/health

Or with a Unicode-laden payload:

curl -H "uber-trace-id: \xef\xbf\xbd:\xef\xbf\xbd:\xef\xbf\xbd:1" \
     https://your-service.example.com/api/orders

When the propagator's extract() method processes this header—which happens before your application code even runs—the malformed input causes an unhandled error. Depending on the Node.js error handling configuration, this can:

  1. Crash the process if the error propagates to the top-level event loop
  2. Hang the request if the parsing enters an unexpected code path that never resolves the async chain
  3. Degrade performance if the malformed input causes excessive CPU consumption in string processing loops

Because the uber-trace-id header is a standard HTTP header that any client can set, this attack is trivially automatable. A single attacker with a basic script can repeatedly send these requests to keep the service unavailable.

Real-world impact for this application

This application uses @opentelemetry/propagator-jaeger in its production codebase (confirmed by its presence in the non-devDependencies section of package.json). That means every inbound HTTP request to this service passes through the vulnerable header extraction logic. There is no "opt-in" path—the propagator is registered globally in the OpenTelemetry SDK and runs on all requests automatically.


The Fix

What changed in package-lock.json

The fix upgrades @opentelemetry/propagator-jaeger from 2.8.0 to 2.9.0. Here's the exact before/after from the diff:

Before (vulnerable):

"node_modules/@opentelemetry/propagator-jaeger": {
  "version": "2.8.0",
  "license": "Apache-2.0",
  "dependencies": {
    "@opentelemetry/core": "2.8.0"
  }
}

After (patched):

"node_modules/@opentelemetry/propagator-jaeger": {
  "version": "2.9.0",
  "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.9.0.tgz",
  "integrity": "sha512-4mYGty27rYvSM0jtp1ZUOqd3LfVRCYg9H5G9OFzSx5HViYToU21MFhWfco7x1HwXr7ER8yGOiCIHZUwjPksc0Q==",
  "license": "Apache-2.0",
  "dependencies": {
    "@opentelemetry/core": "2.9.0"
  },
  "engines": {
    "node": "^18.19.0 || >=20.6.0"
  },
  "peerDependencies": {
    "@opentelemetry/api": ">=1.0.0 <1.10.0"
  }
}

The nested dependency fix

A subtle but critical part of the fix is the addition of a nested @opentelemetry/core resolution specifically scoped to the propagator:

"node_modules/@opentelemetry/propagator-jaeger/node_modules/@opentelemetry/core": {
  "version": "2.9.0",
  "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.9.0.tgz",
  "integrity": "sha512-m2nckMT80NnmjTYSPjJQObBJ+8dgkoajEOUbznL8AHZ3T3yHRk2P7gI1PhEBc1+lOnrYE9UWrWHqJDsmqjmNbw==",
  "license": "Apache-2.0",
  "dependencies": {
    "@opentelemetry/semantic-conventions": "^1.29.0"
  }
}

This matters because npm's dependency resolution can sometimes leave a nested package using an older version of a transitive dependency if another package in the tree has already resolved a different version of @opentelemetry/core. By explicitly pinning @opentelemetry/core at 2.9.0 within the propagator's own node_modules subtree, the fix guarantees the patched parsing logic is actually used—regardless of what other packages in the dependency tree might resolve.

Why version 2.9.0 fixes the problem

Version 2.9.0 of @opentelemetry/core introduces hardened validation in the utility functions responsible for decoding trace IDs and span IDs from the Jaeger header format. The patched code validates:

  • Length bounds — header segments are checked against expected lengths before processing
  • Character set — hex-encoded IDs are validated to contain only valid hexadecimal characters
  • Structural integrity — the split result is checked to have the expected number of segments before array indexing

This means a malformed uber-trace-id header is now silently ignored (the propagator returns a no-op context) rather than throwing an unhandled exception that can crash the service.

The package.json change

The package.json was also updated to explicitly declare @opentelemetry/propagator-jaeger as a direct dependency at ^2.9.0:

"@opentelemetry/propagator-jaeger": "^2.9.0"

This ensures that future npm install runs will not accidentally downgrade the package to a vulnerable version, and makes the security requirement explicit in the project's dependency manifest.


Prevention & Best Practices

1. Keep observability libraries updated

OpenTelemetry libraries sit in the hot path of every request. Unlike a utility library that's only invoked in specific code paths, propagators run on all inbound traffic. This makes them a high-value target for DoS attacks, and it means that vulnerabilities in them have maximum blast radius.

Set up automated dependency scanning (Trivy, Dependabot, Snyk) and treat high-severity CVEs in observability dependencies with the same urgency as vulnerabilities in your own code.

2. Validate headers at the edge

Even with a patched propagator, consider adding a middleware layer that validates or strips unexpected uber-trace-id headers before they reach the OpenTelemetry SDK:

// Express middleware example
app.use((req, res, next) => {
  const traceHeader = req.headers['uber-trace-id'];
  if (traceHeader) {
    // Basic structural validation: {traceId}:{spanId}:{parentSpanId}:{flags}
    const JAEGER_HEADER_REGEX = /^[0-9a-f]{1,32}:[0-9a-f]{1,16}:[0-9a-f]{0,16}:[0-9a-f]{1,2}$/i;
    if (!JAEGER_HEADER_REGEX.test(traceHeader)) {
      delete req.headers['uber-trace-id'];
    }
  }
  next();
});

This defense-in-depth approach ensures that even if a future vulnerability emerges in the propagator, malformed headers are sanitized before they can cause damage.

3. Lock your dependency tree

Always commit your package-lock.json to version control. A lock file ensures that:
- All team members and CI/CD pipelines use identical dependency versions
- Security upgrades (like this one) are reliably applied across all environments
- Nested transitive dependency resolutions are deterministic

4. Use npm audit in your CI pipeline

npm audit --audit-level=high

Add this command to your CI pipeline to catch high and critical severity vulnerabilities before they reach production. Pair it with Trivy for container-level scanning.

5. Relevant security standards

  • OWASP A06:2021 – Vulnerable and Outdated Components: This vulnerability is a textbook example of why keeping dependencies updated is a security requirement, not just a maintenance chore.
  • CWE-400 – Uncontrolled Resource Consumption: The root cause pattern here—failing to validate user-controlled input before resource-intensive processing—is one of the most common DoS vulnerability classes.
  • OWASP Input Validation Cheat Sheet: Recommends validating all input, including HTTP headers, against an allowlist of expected formats.

Key Takeaways

  • @opentelemetry/propagator-jaeger 2.8.0 processes uber-trace-id headers without adequate input validation, meaning any HTTP client can trigger a crash with a single malformed request—no authentication required.
  • The fix is not just a version bump—it also requires pinning the nested @opentelemetry/core dependency to 2.9.0 within the propagator's own module subtree to guarantee the patched parsing logic is actually loaded at runtime.
  • Observability libraries are not exempt from security review. Because they intercept all traffic, a DoS vulnerability in a propagator has the same effective blast radius as a vulnerability in your core request router.
  • Explicitly declaring the patched version in package.json (not just package-lock.json) prevents future npm install runs from silently reverting to a vulnerable version.
  • Trivy's lockfile scanning caught this before it became an incident—scanning package-lock.json for CVEs, not just package.json, is essential because transitive and nested dependencies are invisible to manifest-only scanners.

How Orbis AppSec Detected This

  • Source: The uber-trace-id HTTP header on any inbound request to the application—fully attacker-controlled, requiring no authentication.
  • Sink: The header decoding logic inside @opentelemetry/propagator-jaeger 2.8.0's extract() method, which delegates to string-parsing utilities in @opentelemetry/core 2.8.0 without sufficient input validation.
  • Missing control: No length or character-set validation was performed on the individual segments of the uber-trace-id header value before they were processed as trace and span IDs.
  • CWE: CWE-400 — Uncontrolled Resource Consumption
  • Fix: Upgraded @opentelemetry/propagator-jaeger from 2.8.0 to 2.9.0 in both package.json and package-lock.json, including a pinned nested resolution of @opentelemetry/core at 2.9.0 to ensure the hardened parsing logic is used at runtime.

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-59892 is a sharp reminder that the libraries doing invisible work on every request—like distributed tracing propagators—deserve the same security scrutiny as your application code. A single malformed uber-trace-id header hitting @opentelemetry/propagator-jaeger 2.8.0 was all it took to potentially bring down a production Node.js service. The fix is straightforward: upgrade to 2.9.0, ensure the nested @opentelemetry/core dependency is also resolved to its patched version, and add automated CVE scanning to your CI pipeline so these issues are caught before they reach production.

Observability infrastructure is not a passive bystander—it's active code running in your critical path. Treat it accordingly.


References

Frequently Asked Questions

What is Denial of Service via malformed HTTP header decoding?

It is a vulnerability where an attacker sends a specially crafted HTTP header that the receiving application cannot safely parse, causing it to crash, loop indefinitely, or consume excessive resources—making the service unavailable to legitimate users.

How do you prevent Denial of Service via malformed header decoding in Node.js?

Always validate and sanitize incoming HTTP headers before passing them to parsing logic, use well-maintained libraries that are kept up to date, and apply input length and format checks at the edge (e.g., in middleware) before telemetry propagators ever see the raw header value.

What CWE is Denial of Service via malformed HTTP header decoding?

CWE-400 (Uncontrolled Resource Consumption), which covers cases where an application does not properly control the amount of resources it consumes in response to user-supplied input, enabling an attacker to exhaust those resources.

Is upgrading the package enough to prevent this vulnerability?

Yes, for CVE-2026-59892 the upgrade from 2.8.0 to 2.9.0 is the correct and complete fix. However, you should also ensure your dependency lock file (`package-lock.json`) is updated so that nested transitive dependencies (like `@opentelemetry/core`) are also resolved to their patched versions.

Can static analysis detect Denial of Service via malformed header decoding?

Yes. Tools like Trivy (which flagged this exact vulnerability) scan your dependency lock files against known CVE databases. Semgrep rules can also detect unsafe header-parsing patterns in source code before they reach production.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #1613

Related Articles

medium

How Insufficient Password Hashing Cost Factor Happens in Node.js and How to Fix It

A bcrypt password hashing implementation in the User.js model was using a cost factor of 10, which falls below OWASP's 2024 recommendation of 12 for applications handling sensitive data. This fix upgrades the salt rounds from 10 to 12, increasing the computational work required to crack passwords by approximately 4x, significantly improving protection against brute-force attacks on this e-commerce platform.

high

How Arbitrary Code Execution via Template Imports Happens in JavaScript (lodash) and How to Fix It

A high-severity arbitrary code execution vulnerability (CVE-2026-4800) was discovered in lodash's template function, specifically in how it handles the `imports` option with untrusted input. The fix upgrades lodash from version 4.17.21 to 4.18.0 in the project's `package.json` and `yarn.lock`, eliminating the attack surface where crafted template imports could execute arbitrary code on the server.

critical

How Server-Side Request Forgery (SSRF) happens in Node.js IP address parsing and how to fix it

A critical SSRF vulnerability (CVE-2026-69192) was discovered in the ip-address npm package version 10.2.0, which could allow attackers to bypass IP address validation and access internal services. The fix upgrades the dependency to version 10.3.1, which properly handles edge cases in IP address parsing that previously allowed trust-boundary bypasses.

critical

How Sensitive Data Exposure happens in Python web applications and how to fix it

A critical sensitive data exposure vulnerability was discovered in `nodes/google_gemini.py` where the Google Gemini API key was returned in plaintext through a web endpoint. The fix masks the token in API responses, preventing credential theft from any client that queries the token endpoint. This protects downstream users of this Node.js library from unauthorized access to their Google Gemini services.

high

How Authentication Bypass happens in Next.js App Router with Turbopack and how to fix it

A critical authentication bypass vulnerability (CVE-2026-64642) was discovered in Next.js versions prior to 16.2.11, specifically affecting App Router applications using Turbopack with a single locale configuration. This vulnerability allowed attackers to bypass middleware and proxy protections, potentially gaining unauthorized access to protected routes and resources that should have been secured by authentication checks.

critical

How SQL Injection Happens in CSV-to-SQL Converters and How to Fix It

A critical SQL injection vulnerability was discovered in the `csv2sql()` function in `src/data/converter/csv.js`, where CSV data and table names were directly interpolated into SQL INSERT statements without sanitization. The fix implements input validation through identifier sanitization and proper value escaping, eliminating the attack surface while preserving legitimate functionality.