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:
- Robust header format validation: The decoder now validates the header structure before attempting to parse individual components, rejecting malformed headers early
- Bounds checking: All string operations include length checks to prevent buffer overruns or excessive memory allocation
- Safe parsing: Hexadecimal parsing includes validation to ensure only valid characters are processed
- Error isolation: Exceptions during header decoding are caught and logged, returning an invalid span context instead of crashing
- 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-jaeger2.7.1 package failed to validate Jaeger trace context headers, allowing malformeduber-trace-idheaders 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/corecan 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-idand baggage headers) from external clients or upstream services - Sink:
@opentelemetry/propagator-jaeger@2.7.1header 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-jaegerfrom 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.