Back to Blog
high SEVERITY7 min read

How Denial of Service via malformed HTTP header decoding happens in OpenTelemetry JavaScript and how to fix it

A high-severity Denial of Service vulnerability (CVE-2026-59892) was discovered in @opentelemetry/propagator-jaeger version 2.7.1, where malformed HTTP headers could crash Node.js applications during trace context decoding. The vulnerability was fixed by upgrading from version 2.7.1 to 2.9.0, which includes improved header validation and error handling to prevent application crashes from malicious or corrupted trace propagation headers.

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

Answer Summary

CVE-2026-59892 is a Denial of Service vulnerability in @opentelemetry/propagator-jaeger (Node.js/JavaScript) where malformed HTTP headers cause application crashes during Jaeger trace context decoding. The vulnerability affects version 2.7.1 and was fixed by upgrading to version 2.9.0, which adds robust header validation and error handling to prevent crashes from invalid trace propagation data. This is classified as a high-severity issue because it allows attackers to crash distributed tracing infrastructure with crafted HTTP requests.

Vulnerability at a Glance

cweCWE-20 (Improper Input Validation)
fixUpgrade @opentelemetry/propagator-jaeger from 2.7.1 to 2.9.0
riskApplication crashes from malicious HTTP headers in distributed tracing
languageJavaScript/Node.js
root causeInsufficient validation of Jaeger trace context headers before decoding
vulnerabilityDenial of Service via malformed HTTP header decoding

Introduction

In a production Node.js application using OpenTelemetry for distributed tracing, we discovered a high-severity Denial of Service vulnerability in the @opentelemetry/propagator-jaeger package version 2.7.1. The vulnerability, tracked as CVE-2026-59892, lurked in the bun.lock dependency file and could allow attackers to crash the entire application by sending malformed HTTP headers containing invalid Jaeger trace context data.

This isn't a theoretical risk—the Jaeger propagator processes HTTP headers on every incoming request that includes distributed tracing information. When the propagator encounters a malformed uber-trace-id header or corrupted baggage data, version 2.7.1 fails to handle the error gracefully, potentially throwing unhandled exceptions that can terminate the Node.js process. For applications handling thousands of requests per second, a single malicious request could bring down critical services.

The vulnerability affects any Node.js application using @opentelemetry/propagator-jaeger 2.7.1 for distributed tracing, particularly those exposing HTTP endpoints that accept trace context headers from untrusted sources like public APIs, microservice meshes, or third-party integrations.

The Vulnerability Explained

The @opentelemetry/propagator-jaeger package implements the Jaeger trace context propagation format for OpenTelemetry. When a request arrives with tracing headers, the propagator extracts trace IDs, span IDs, and baggage from HTTP headers like uber-trace-id. Version 2.7.1 had insufficient validation during the header decoding process.

Here's what the vulnerable dependency looked like in the lock file:

"@opentelemetry/propagator-jaeger": ["@opentelemetry/propagator-jaeger@2.7.1", "", { 
  "dependencies": { "@opentelemetry/core": "2.7.1" }, 
  "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } 
}, "sha512-KMjVBHzP4N60bOzxja76M1F1hZZ43lGPga5ix+mkv9+kk1nx9SbkxSvJsMbuVUxdPQmsPTqGShmhN8ulrMOg6Q=="]

The vulnerability manifests when the propagator attempts to decode malformed trace context data. The Jaeger format expects headers in a specific structure: {trace-id}:{span-id}:{parent-span-id}:{flags}. When an attacker sends a header like:

uber-trace-id: malformed:::::::data:with:too:many:colons

Or with invalid hexadecimal values:

uber-trace-id: ZZZZZZZZ:YYYYYYYY:0:1

Version 2.7.1's decoder attempts to parse these values without proper bounds checking or format validation. The parsing logic throws exceptions that may not be caught by application-level error handlers, particularly in middleware chains where the propagator runs early in the request lifecycle.

Attack Scenario

Consider a microservices architecture where Service A calls Service B, and both use OpenTelemetry with Jaeger propagation. An attacker discovers that Service B's public API endpoint at https://api.example.com/v1/data accepts trace context headers. The attacker crafts a request:

curl -H "uber-trace-id: ffffffffffffffff:ffffffffffffffff:0:1:baggage=\x00\x00\x00" \
     https://api.example.com/v1/data

When Service B's OpenTelemetry middleware processes this request, the @opentelemetry/propagator-jaeger@2.7.1 package attempts to decode the null bytes in the baggage section. The decoder throws an unhandled exception, causing the Node.js event loop to crash. The service becomes unavailable, affecting all downstream consumers and triggering cascading failures across the distributed system.

The real-world impact is severe:
- Service disruption: A single malformed request can crash the entire Node.js process
- Cascading failures: In microservice architectures, one crashed service can trigger timeouts and failures across multiple services
- Easy exploitation: The attack requires only HTTP header manipulation, no authentication
- Amplification: Automated tools or compromised services can repeatedly send malformed headers

The Fix

The fix involved upgrading @opentelemetry/propagator-jaeger from version 2.7.1 to 2.9.0, which includes comprehensive improvements to header validation and error handling. The upgrade also updates the underlying @opentelemetry/core dependency from 2.7.1 to 2.9.0.

Before (Vulnerable Code):

"@opentelemetry/propagator-jaeger": ["@opentelemetry/propagator-jaeger@2.7.1", "", { 
  "dependencies": { "@opentelemetry/core": "2.7.1" }, 
  "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } 
}, "sha512-KMjVBHzP4N60bOzxja76M1F1hZZ43lGPga5ix+mkv9+kk1nx9SbkxSvJsMbuVUxdPQmsPTqGShmhN8ulrMOg6Q=="]

After (Fixed Code):

"@opentelemetry/propagator-jaeger": ["@opentelemetry/propagator-jaeger@2.9.0", "", { 
  "dependencies": { "@opentelemetry/core": "2.9.0" }, 
  "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } 
}, "sha512-4mYGty27rYvSM0jtp1ZUOqd3LfVRCYg9H5G9OFzSx5HViYToU21MFhWfco7x1HwXr7ER8yGOiCIHZUwjPksc0Q=="]

The new dependency entry was also added to the project's package manifest:

+    "@opentelemetry/propagator-jaeger": "2.9.0",

What Changed in Version 2.9.0

Version 2.9.0 of @opentelemetry/propagator-jaeger introduces several critical security improvements:

  1. Robust header format validation: The decoder now validates the header structure before attempting to parse individual components, rejecting malformed headers early
  2. Bounds checking: All string operations include length checks to prevent buffer overruns or excessive memory allocation
  3. Safe parsing: Hexadecimal parsing includes validation to ensure only valid characters are processed
  4. Error isolation: Exceptions during header decoding are caught and logged, returning an invalid span context instead of crashing
  5. Baggage sanitization: Special characters and control codes in baggage items are properly escaped or rejected

These changes ensure that even when an attacker sends malformed headers, the application continues processing requests normally. The propagator simply logs the invalid header and proceeds without valid trace context, maintaining service availability.

The fix also updates @opentelemetry/core to 2.9.0, which provides improved error handling utilities used by the propagator. This coordinated upgrade ensures consistent behavior across the OpenTelemetry stack.

Prevention & Best Practices

To prevent similar vulnerabilities in distributed tracing implementations:

1. Validate All External Input

Always validate HTTP headers before processing, especially those from untrusted sources. For trace context headers:

function validateJaegerHeader(header) {
  if (!header || typeof header !== 'string') return false;
  if (header.length > 1024) return false; // Prevent DoS via large headers

  const parts = header.split(':');
  if (parts.length < 4) return false;

  // Validate hex format for trace and span IDs
  const hexRegex = /^[0-9a-f]+$/i;
  if (!hexRegex.test(parts[0]) || !hexRegex.test(parts[1])) return false;

  return true;
}

2. Use Try-Catch Around External Library Calls

Even when using well-maintained libraries, wrap parsing operations in try-catch blocks:

try {
  const spanContext = propagator.extract(context, carrier, getter);
  // Process trace context
} catch (error) {
  logger.warn('Failed to extract trace context', { error: error.message });
  // Continue without tracing rather than crashing
}

3. Keep Dependencies Updated

Regularly update OpenTelemetry and other security-critical dependencies. Use tools like:
- Dependabot: Automated pull requests for dependency updates
- Renovate: Intelligent dependency update automation
- npm audit or pnpm audit: Identify known vulnerabilities in dependencies
- Trivy: Comprehensive vulnerability scanning for container images and dependencies

4. Implement Defense in Depth

Don't rely solely on library validation:
- Set maximum header size limits at the HTTP server level
- Use rate limiting to prevent DoS attempts
- Implement circuit breakers for distributed tracing to prevent cascading failures
- Monitor for unusual patterns in trace header formats

5. Test with Malformed Input

Include fuzzing and negative test cases in your test suite:

describe('Trace propagation', () => {
  it('should handle malformed uber-trace-id headers', () => {
    const malformedHeaders = [
      'invalid',
      ':::',
      'ZZZZ:YYYY:0:1',
      'a'.repeat(10000), // Very long header
      '\x00\x00\x00', // Null bytes
    ];

    malformedHeaders.forEach(header => {
      expect(() => {
        propagator.extract(context, { 'uber-trace-id': header }, getter);
      }).not.toThrow();
    });
  });
});

6. Follow OWASP Guidelines

Refer to the OWASP Input Validation Cheat Sheet for comprehensive input validation strategies.

Key Takeaways

  • The @opentelemetry/propagator-jaeger 2.7.1 package failed to validate Jaeger trace context headers, allowing malformed uber-trace-id headers to crash Node.js applications through unhandled exceptions
  • Upgrading to version 2.9.0 adds robust header validation and error handling that prevents crashes even when processing malicious or corrupted trace propagation data
  • Distributed tracing libraries are attack surfaces because they process headers from potentially untrusted sources on every request—treat them as security-critical components
  • Lock file dependencies need regular security scanning since vulnerabilities in transitive dependencies like @opentelemetry/core can impact your application's security posture
  • Always wrap external library parsing operations in try-catch blocks to prevent unhandled exceptions from crashing your application, even when using reputable libraries

How Orbis AppSec Detected This

  • Source: HTTP request headers containing Jaeger trace context (uber-trace-id and baggage headers) from external clients or upstream services
  • Sink: @opentelemetry/propagator-jaeger@2.7.1 header decoding logic that processes trace context without sufficient validation
  • Missing control: Input validation for header format, length limits, character encoding validation, and exception handling around parsing operations
  • CWE: CWE-20 (Improper Input Validation) and CWE-400 (Uncontrolled Resource Consumption)
  • Fix: Upgraded @opentelemetry/propagator-jaeger from 2.7.1 to 2.9.0, which includes comprehensive header validation and error isolation

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 demonstrates that even well-maintained observability libraries can harbor critical vulnerabilities when processing external input. The Denial of Service vulnerability in @opentelemetry/propagator-jaeger 2.7.1 could have allowed attackers to crash production services with a single malformed HTTP header, highlighting the importance of treating distributed tracing infrastructure as a security boundary.

The fix—upgrading to version 2.9.0—shows the value of keeping dependencies current and using automated security scanning. By implementing robust input validation, proper error handling, and regular dependency updates, you can protect your distributed systems from similar vulnerabilities while maintaining observability.

Remember: every external input is a potential attack vector. Whether it's user data, API parameters, or distributed tracing headers, validate rigorously and fail gracefully.

References

Frequently Asked Questions

What is Denial of Service via malformed HTTP header decoding?

It's a vulnerability where an application crashes or becomes unresponsive when processing specially crafted HTTP headers. In this case, the OpenTelemetry Jaeger propagator failed to validate trace context headers, allowing malformed data to trigger exceptions that could crash the Node.js process.

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

Implement strict input validation on all HTTP headers before processing, use try-catch blocks around header parsing logic, set maximum header size limits, validate header format against expected schemas, and use libraries that have been hardened against malformed input (like @opentelemetry/propagator-jaeger 2.9.0+).

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

This vulnerability maps to CWE-20 (Improper Input Validation) and CWE-400 (Uncontrolled Resource Consumption). The root cause is failing to validate input data before processing, which allows malicious input to consume resources or trigger crashes.

Is rate limiting enough to prevent Denial of Service from malformed headers?

No, rate limiting alone is insufficient. While it can reduce the frequency of attacks, a single malformed request can still crash the application. You need input validation, proper error handling, and defensive parsing in addition to rate limiting for comprehensive protection.

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

Yes, static analysis tools like Trivy can detect vulnerable library versions with known CVEs. However, detecting the underlying code pattern requires dependency scanning combined with vulnerability databases. In this case, Trivy identified the vulnerable @opentelemetry/propagator-jaeger version 2.7.1 in the bun.lock file.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #1380

Related Articles

high

How Quadratic CPU Consumption Vulnerabilities Happen in JavaScript YAML Parsers and How to Fix Them

A high-severity denial-of-service vulnerability in js-yaml versions 3.x and 4.x allowed attackers to trigger quadratic CPU consumption through specially crafted YAML documents using the !!omap tag. This fix upgrades js-yaml from 4.1.1 to 4.3.1 and from 3.14.2 to 3.15.1, eliminating the algorithmic complexity attack vector that could freeze Node.js applications processing untrusted YAML input.

high

How javascript.lang.security.detect-child-process.detect-child-process happens in Node.js and how to fix it

A high-severity command injection vulnerability was discovered in `scripts/build.js` where `execSync` was called with string-interpolated arguments (`sourceDir` and `outputPath`) inside a shell command. By replacing `execSync` with `spawnSync` using an argument array (no shell), the fix eliminates the possibility of shell metacharacter injection while preserving identical build behavior.

high

How Command Injection happens in Node.js child_process and how to fix it

A command injection vulnerability in nix.js's Release class allowed potentially malicious input through the `arch` parameter to be executed via shell commands. The fix replaced `execSync()` with `execFileSync()`, eliminating shell interpretation and preventing command injection by passing arguments as an array instead of a concatenated string.

critical

How Sensitive Data Exposure in Error Logging happens in TypeScript/Deno and how to fix it

A critical vulnerability in Supabase Edge Functions allowed sensitive authentication errors and API credentials to leak through verbose error logging. The `cancel-subscription/index.ts` function logged full error objects to the console, potentially exposing Paddle API keys and auth tokens in deployment logs. The fix sanitizes all error messages to log only safe error text while preserving debugging capability.

critical

How HTTP Header Injection Happens in Go and How to Fix It

A critical vulnerability in the file upload handler allowed attackers to inject CRLF sequences into HTTP response headers through crafted filenames. The fix sanitizes user-supplied filenames before using them in Content-Disposition headers, preventing header injection attacks that could lead to cache poisoning, session fixation, or XSS.

high

How Path Traversal and Security Policy Bypass Happens in Node.js Dependencies and How to Fix It

A high-severity vulnerability in the fast-uri package (CVE-2026-6321) allowed attackers to bypass security policies through improper Unicode hostname canonicalization and path traversal. This issue affected the @apralabs/apra-fleet project through its dependency tree, and was resolved by upgrading fast-uri from version 3.1.0 to 4.1.2 using npm overrides.