Nov 14, 2026·10 min read·1 visit
Versions 0.204.0 to < 0.222.0 of @opentelemetry/instrumentation-http fail to redact sensitive query string parameters on incoming HTTP server spans. Raw query parameters are written verbatim to the url.query attribute and exported to tracing backends, exposing credentials such as AWS/GCS pre-signed signatures and API keys to users with telemetry read access. Upgrade to version 0.222.0 or later to remediate.
An information exposure vulnerability in the @opentelemetry/instrumentation-http package for OpenTelemetry JavaScript versions 0.204.0 prior to 0.222.0 causes incoming HTTP server spans to record raw, unredacted query string parameters under the url.query attribute. While outgoing client spans applied built-in and user-configured query parameter redaction, incoming server spans bypassed this sanitization completely, resulting in the transmission of sensitive credentials such as pre-signed cloud URLs and API tokens to external observability backends.
The @opentelemetry/instrumentation-http package provides automatic tracing and telemetry collection for Node.js http and https modules within the OpenTelemetry JavaScript ecosystem. It intercepts both outgoing client HTTP requests and incoming server HTTP requests to generate telemetry spans compliant with OpenTelemetry semantic conventions. These spans capture request metadata, including URL paths, query strings, headers, and status codes, before exporting the data to configured observability backends such as Jaeger, Zipkin, Datadog, or Honeycomb.
In versions 0.204.0 through 0.221.x (prior to 0.222.0), an asymmetric sanitization flaw exists in how query string parameters are processed across client and server spans. When generating outgoing client spans, the instrumentation applies a redaction mechanism that replaces the values of known sensitive query parameters (such as sig, Signature, AWSAccessKeyId, and X-Goog-Signature) with the string REDACTED before recording the url.full span attribute. However, when generating incoming server spans, the instrumentation extracts the raw query string and writes it directly to the url.query span attribute without invoking any redaction routines.
Furthermore, the package exposes a configuration option named redactedQueryParams intended to allow developers to specify custom query parameter names for sanitization. Because the incoming request handler completely omits the redaction code path, configuring redactedQueryParams has no effect on server spans, rendering the documented security control inert for incoming traffic.
This vulnerability is classified under CWE-532 (Insertion of Sensitive Information into Log File) and CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor). Services that receive credentials, webhook secrets, or pre-signed cloud storage URLs via HTTP query parameters inadvertently export valid, plaintext secrets to external tracing infrastructure, where they can be accessed by any entity with telemetry read permissions.
The root cause of CVE-2026-128080 is an architectural omission in the request attribute extraction logic within experimental/packages/opentelemetry-instrumentation-http/src/utils.ts. In OpenTelemetry semantic conventions, outgoing client requests record the complete URL in the url.full attribute (ATTR_URL_FULL), whereas incoming server requests decompose the URL and record the query string independently in the url.query attribute (ATTR_URL_QUERY).
When the redaction feature was originally implemented, the sanitization loop was embedded directly inside the getAbsoluteUrl() helper function. Because getAbsoluteUrl() is exclusively invoked during outgoing client request processing to construct ATTR_URL_FULL, the redaction logic was tightly coupled to the client span creation path.
Conversely, incoming HTTP requests are processed by the getIncomingRequestAttributes() function in src/utils.ts. To populate the server span attributes, getIncomingRequestAttributes() parses the incoming request URL via getInfoFromIncomingMessage() and checks for the presence of the parsedUrl.search property. In vulnerable versions, the function slices the leading ? character from parsedUrl.search and assigns the resulting raw string directly to attributes[ATTR_URL_QUERY].
In addition to the missing server-side sanitization, the original client-side redaction implementation in getAbsoluteUrl() contained a secondary logic flaw in how it checked for parameter presence. It evaluated if (parsedUrl.searchParams.get(sensitiveParam)) before masking the value. In the standard WHATWG URLSearchParams API, .get() returns an empty string "" if a parameter is present with no value (e.g., ?sig=), which evaluates to falsy in JavaScript, bypassing redaction for empty parameters and failing to account cleanly for duplicate parameter keys.
A comparison of the source code before and after commit e086dec7f9304107ef6d50b5877be88895c06aa7 demonstrates both the vulnerable code path and the structural changes introduced to unify parameter redaction.
In the vulnerable versions (>= 0.204.0, < 0.222.0), getAbsoluteUrl() handled redaction inline, while getIncomingRequestAttributes() bypassed it entirely:
// VULNERABLE CODE: experimental/packages/opentelemetry-instrumentation-http/src/utils.ts
export const getAbsoluteUrl = (
requestUrl: ParsedRequestOptions,
headers: OutgoingHttpHeaders,
component: 'http' | 'https' = 'http',
redactedQueryParams?: string[]
): string => {
// ... [host and port construction omitted] ...
if (path.includes('?')) {
try {
const parsedUrl = new URL(path, 'http://localhost');
const sensitiveParamsToRedact: string[] = redactedQueryParams || [];
// Redaction only occurs here on the client path,
// and .get() fails on empty strings
for (const sensitiveParam of sensitiveParamsToRedact) {
if (parsedUrl.searchParams.get(sensitiveParam)) {
parsedUrl.searchParams.set(sensitiveParam, STR_REDACTED);
}
}
path = `${parsedUrl.pathname}${parsedUrl.search}`;
} catch {
// Ignore error, as the path was not a valid URL.
}
}
return `${component}://${host}${path}`;
};
export const getIncomingRequestAttributes = (
request: IncomingMessage,
options: {
component: 'http' | 'https';
hookAttributes?: Attributes;
enableSyntheticSourceDetection: boolean;
// Missing redactedQueryParams option in signature
},
logger: DiagLogger
): Attributes => {
// ... [attribute extraction omitted] ...
if (parsedUrl.search) {
// VULNERABILITY: Raw query string assigned directly without sanitization
attributes[ATTR_URL_QUERY] = parsedUrl.search.slice(1);
}
// ...
};In the remediation commit (e086dec7f9304107ef6d50b5877be88895c06aa7), the maintainers extracted a dedicated redactQueryString() utility function and invoked it across both getAbsoluteUrl() and getIncomingRequestAttributes(). They also expanded DEFAULT_QUERY_STRINGS_TO_REDACT in src/internal-types.ts to cover AWS Signature Version 4 parameters (X-Amz-Signature, X-Amz-Credential, X-Amz-Security-Token).
// PATCHED CODE: experimental/packages/opentelemetry-instrumentation-http/src/utils.ts
const defaultQueryStringsToRedact = Array.from(DEFAULT_QUERY_STRINGS_TO_REDACT);
/**
* Redacts sensitive query parameters from a query string (without leading '?').
* Returns the input unchanged if it cannot be parsed.
*/
export const redactQueryString = (
searchParams: URLSearchParams,
paramsToRedact: string[]
): string => {
const params = new URLSearchParams(searchParams);
for (const param of paramsToRedact) {
// Uses .has() instead of .get() to ensure empty and duplicate params are overwritten
if (params.has(param)) {
params.set(param, STR_REDACTED);
}
}
return params.toString();
};Within getIncomingRequestAttributes(), the patched implementation now accepts redactedQueryParams in its options object (populated in src/http.ts from instrumentation.getConfig().redactedQueryParamsServer ?? Array.from(DEFAULT_QUERY_STRINGS_TO_REDACT)) and sanitizes parsedUrl.search before assignment:
// PATCHED CODE: getIncomingRequestAttributes() in src/utils.ts
if (parsedUrl.search) {
// Remove leading '?' from URL search
const paramsToRedact = redactedQueryParams ?? defaultQueryStringsToRedact;
attributes[ATTR_URL_QUERY] = redactQueryString(
new URLSearchParams(parsedUrl.search.slice(1)),
paramsToRedact
);
}> [!NOTE]
> Assessment of Fix Completeness: While the patch resolves the missing server-side redaction and fixes empty/duplicate parameter handling via params.has(param), two design caveats remain. First, parameter matching in URLSearchParams.has() is strictly case-sensitive; an incoming query string using lowercase x-amz-signature or uppercase SIG will not match the default list unless explicitly added by the developer. Second, redactedQueryParams (client) and redactedQueryParamsServer (server) do not fall back to one another. If an application upgrades to 0.222.0 and only has redactedQueryParams: ['api_key'] in its existing configuration, server spans will fall back to the built-in default list and will not redact api_key until redactedQueryParamsServer is also explicitly configured.
Exploitation of CVE-2026-128080 does not involve active memory corruption or direct payload injection against the Node.js server. Instead, it is a passive credential harvesting attack targeting the boundary between the application runtime and the observability infrastructure.
Prerequisites for Exploitation:
@opentelemetry/instrumentation-http (versions >= 0.204.0, < 0.222.0) and exports traces to a centralized observability platform.Attack Methodology:
When a legitimate client or upstream webhook provider sends an HTTP request to the instrumented Node.js server—for example, a callback carrying a pre-signed cloud storage URL or an authentication parameter—the HTTP instrumentation intercepts the IncomingMessage event:
GET /api/v1/webhook/storage-sync?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Signature=vjbyPxybdZaNmGa%2ByT272YEAiv4%3D&Expires=1790000000 HTTP/1.1
Host: vulnerable-service.internalThe server creates a span for the GET request and populates attributes['url.query'] with the raw string AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Signature=vjbyPxybdZaNmGa%2ByT272YEAiv4%3D&Expires=1790000000. Once the span finishes, the configured SpanExporter transmits this record to the tracing backend.
An adversary with span-read privileges queries the observability platform for spans containing url.query attributes matching patterns such as *Signature=*, *AWSAccessKeyId=*, *X-Amz-Security-Token=*, or *api_key=*. If the extracted token or pre-signed URL has not yet expired (Expires=1790000000), the attacker replays the harvested credentials directly against the target resource or cloud service, bypassing the application security boundary.
The severity of CVE-2026-128080 is rated as Medium with a CVSS v3.1 base score of 5.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N). The Attack Vector is Network (AV:N) with Low Attack Complexity (AC:L), requiring No Privileges (PR:N) and No User Interaction (UI:N) to trigger the trace recording.
A critical aspect of the CVSS vector is the Changed Scope (S:C). While the vulnerable code executes within the Node.js application runtime, the security impact manifests across a separate security domain: the external observability and telemetry storage infrastructure. Organizations routinely grant broad read access to APM and distributed tracing systems across engineering, DevOps, and support teams under the assumption that sensitive authentication material is scrubbed prior to export.
The Confidentiality impact is scored as Low (C:L) in the base vector because the vulnerability only exposes parameters transmitted in query strings rather than granting arbitrary read access to server memory or environment variables. However, in practical cloud environments where AWS S3 pre-signed URLs (X-Amz-Signature, X-Amz-Security-Token), Google Cloud Storage signed URLs (X-Goog-Signature), or OAuth code / bearer tokens are passed via query parameters, credential disclosure enables direct unauthorized access to protected data stores.
According to threat intelligence data, CVE-2026-128080 is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog, has no cataloged public exploit code in ExploitDB or Metasploit, and maintains an EPSS score of 0%.
To remediate CVE-2026-128080, upgrade @opentelemetry/instrumentation-http to version 0.222.0 (experimental/v0.222.0) or later. In version 0.222.0, incoming server spans automatically redact the built-in list of sensitive query parameters (sig, Signature, AWSAccessKeyId, X-Goog-Signature, X-Amz-Signature, X-Amz-Credential, X-Amz-Security-Token).
npm install @opentelemetry/instrumentation-http@^0.222.0Important Configuration Requirement for Custom Parameters:
If your application relies on custom query parameter redaction (e.g., api_key, access_token, auth), upgrading the package alone is not sufficient if you previously configured redactedQueryParams. In version 0.222.0, redactedQueryParams only controls client spans, while the newly introduced redactedQueryParamsServer option controls server spans. Furthermore, passing a custom array replaces the built-in default list rather than merging with it. Developers must explicitly provide the full list to both options:
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const redactedParams = [
// Built-in defaults
'sig',
'Signature',
'AWSAccessKeyId',
'X-Goog-Signature',
'X-Amz-Signature',
'X-Amz-Credential',
'X-Amz-Security-Token',
// Application-specific custom parameters
'api_key',
'access_token'
];
const httpInstrumentation = new HttpInstrumentation({
redactedQueryParams: redactedParams,
redactedQueryParamsServer: redactedParams,
});Workarounds for Unpatched Environments:
If an immediate upgrade to 0.222.0 cannot be deployed, operators can sanitize the url.query attribute before spans are exported by registering a custom OpenTelemetry SpanProcessor (or using the requestHook configuration in HttpInstrumentation to overwrite url.query):
const { ATTR_URL_QUERY } = require('@opentelemetry/semantic-conventions');
const PARAMS_TO_REDACT = [
'sig', 'Signature', 'AWSAccessKeyId', 'X-Goog-Signature',
'X-Amz-Signature', 'X-Amz-Credential', 'X-Amz-Security-Token'
];
class QueryRedactingSpanProcessor {
onStart(span, parentContext) {
const rawQuery = span.attributes[ATTR_URL_QUERY];
if (typeof rawQuery === 'string' && rawQuery.length > 0) {
const params = new URLSearchParams(rawQuery);
for (const key of PARAMS_TO_REDACT) {
if (params.has(key)) {
params.set(key, 'REDACTED');
}
}
span.setAttribute(ATTR_URL_QUERY, params.toString());
}
}
onEnd(span) {}
shutdown() { return Promise.resolve(); }
forceFlush() { return Promise.resolve(); }
}In addition to code-level remediation, security teams should audit existing trace storage backends for historical exposure of active credentials in url.query attributes and rotate any long-lived API keys or tokens discovered in telemetry records.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@opentelemetry/instrumentation-http OpenTelemetry | >= 0.204.0, < 0.222.0 | 0.222.0 |
| Attribute | Detail |
|---|---|
| CVE / Advisory ID | CVE-2026-128080 / GHSA-3v2p-hm54-8qcq |
| Affected Package | @opentelemetry/instrumentation-http (0.204.0 to < 0.222.0) |
| Weakness Class | CWE-532 (Sensitive Info in Logs) / CWE-200 (Information Exposure) |
| CVSS v3.1 Score | 5.8 Medium (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N) |
| Attack Vector | Network (Unauthenticated HTTP requests with query parameters) |
| Security Impact | Plaintext export of query string credentials (url.query) to tracing backends |
| Exploit / KEV Status | No known public exploits; Not listed in CISA KEV (EPSS: 0%) |
| Patched Version | 0.222.0 (experimental/v0.222.0) |
The product generates a log file, trace, or audit record that contains sensitive information, such as passwords, tokens, or credentials, which may be accessible to unauthorized entities.
CVE-2026-128089 is an uncontrolled resource consumption vulnerability in the dnspython toolkit for Python, affecting all versions prior to 2.9.2. When parsing Well-Known Service (WKS) records from text via dns.rdtypes.IN.WKS.WKS.from_text(), the parser fails to validate that numeric service port identifiers fall within the RFC 1035 valid range of 0 through 65535. An attacker capable of supplying untrusted zone files or RDATA text strings containing an arbitrarily large service port integer can force the parser to allocate an unbounded bitmap array using an inefficient linear append loop, resulting in severe CPU exhaustion, application hangs, or Out-Of-Memory (OOM) process termination.
CVE-2026-126347 (GHSA-5cjw-f85j-cv6r) is an open redirect vulnerability (CWE-601) in Tornado, an asynchronous Python networking library and web framework. The flaw resides in tornado.web.RedirectHandler when dynamic URL redirection templates incorporate unvalidated user input. Due to a parser differential between RFC 3986 (used by Python's urllib.parse.urlsplit) and the WHATWG URL Standard (used by modern web browsers), inputs containing three or more leading slashes bypass Tornado 6.6.0's validation logic, allowing unauthenticated attackers to redirect users to arbitrary external domains.
A Denial of Service (DoS) vulnerability exists in @sveltejs/adapter-node versions 5.5.7 and 6.0.0-next.0 through 6.0.0. When a SvelteKit server route returns a direct response from a fetch() call with a Content-Type of text/event-stream, the Node.js adapter attempts to mutate the response headers to disable proxy buffering. Because headers returned directly by the WHATWG Fetch API carry an immutable guard, this mutation throws an unhandled TypeError, terminating the underlying Node.js process and denying service to all active and subsequent clients.
CVE-2026-128122 (GHSA-5wg4-q3ww-283h) is a build-time CRLF and wildcard injection vulnerability in `@sveltejs/adapter-cloudflare`. During the prerendering phase of a SvelteKit build, the adapter writes crawled redirect paths directly into the Cloudflare `_redirects` and `_routes.json` configuration files without output encoding or character validation. An attacker capable of controlling link paths on prerendered pages can inject newline characters, spaces, or wildcard patterns to forge arbitrary edge redirection rules, enabling asset hijacking and Stored Cross-Site Scripting (XSS).
A vulnerability classified under CWE-116 (Improper Encoding or Escaping of Output) and CWE-625 (Permissive Regular Expression) exists in the @sveltejs/adapter-vercel and @sveltejs/adapter-static packages for SvelteKit. During the build-time prerendering phase, pathnames discovered by the SvelteKit link crawler are inserted into the generated Vercel routing configuration (.vercel/output/config.json) without escaping regular expression metacharacters. Because the Vercel edge routing engine evaluates the 'src' property of route entries as regular expressions, an attacker capable of injecting links into prerendered application content can introduce arbitrary regular expression syntax, hijacking application routing and exposing unintended assets or responses.
CVE-2026-128117 (GHSA-mw6w-2fmv-pvw3) is a denial of service (DoS) vulnerability in SvelteKit (@sveltejs/kit) caused by an uncaught URIError exception during request routing. When an application implements a reroute hook that rewrites a request pathname containing invalid percent-encoding into a valid route, SvelteKit subsequently calls decode_pathname on the original unvalidated url.pathname outside of a try...catch block. In deployments utilizing @sveltejs/adapter-node, this unhandled exception terminates the Node.js runtime process.