Sep 17, 2026·5 min read·3 visits
Unsanitized logging of request query parameters in Steeltoe's HttpExchanges actuator endpoint leaks secrets (OAuth tokens, API keys) in memory and debug log files to unauthorized actors.
Steeltoe, a popular framework for building cloud-native .NET applications, contains a critical data-exposure flaw in its HttpExchanges actuator endpoint before version 4.3.0. When explicitly configured to include query strings, the system records and stores sensitive values (such as OAuth tokens and credentials) in memory and application debug logs without sanitization, exposing them to unauthorized network actors.
The Steeltoe.Management.Endpoint framework provides telemetry and diagnostic utilities for cloud-native .NET applications. One of these utilities, the HTTP Exchanges Actuator (/actuator/httpexchanges), monitors and records historical details about HTTP requests and responses passing through the application. This diagnostic information is designed to assist administrators in monitoring application traffic and diagnosing connectivity issues.
However, a severe information disclosure flaw exists within versions of Steeltoe preceding version 4.3.0. When the HTTP Exchanges actuator is exposed and configured to include query parameters via the Management:Endpoints:HttpExchanges:IncludeQueryString = true setting, the framework fails to sanitize or mask sensitive arguments passed inside the request URI.
This lack of sanitization exposes systems to CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor). If the endpoint is left unauthenticated or poorly restricted, any network-adjacent actor can query the actuator and read operational secrets. Furthermore, when the framework's debug-level logger is enabled, the unmasked URIs are also written to application log files in cleartext, resulting in secondary credential leakage.
The root cause of this vulnerability lies in the design and implementation of the internal MaskedUri structure within Steeltoe's common extensions. When the actuator captures request payloads, it attempts to pass the target URI through MaskedUri to strip sensitive information before storing the transaction in an in-memory buffer.
In the legacy codebase, the MaskedUri constructor only performed sanitization on the UserInfo subcomponent of the URI, which is the basic-authentication block containing username:password in the authority segment. The masking routine completely ignored the query string section of the URI. If the basic-authentication credentials were not present, the masking function immediately returned the raw URI object without modifying or parsing its query parameters.
Additionally, the evaluation of the MaskedUri struct was deferred until JSON serialization. The HttpExchangeRequest component stored the raw, unmasked Uri instance directly in the application's memory pool. This storage mechanism allowed other application tasks, such as internal diagnostic logging routines written via LogIncomingExchange, to read and print the raw, unmasked query parameter data directly into persistent debug log files.
The official patch introduced in commit 9bf0ecb9f2d4a34b65f61d41c5625d49071ae9fa refactored the masking logic. It implemented a robust substring matching filter against query keys and shifted the execution of URI masking to the initiation step of the HttpExchangeRequest class, completely eliminating the deferred evaluation issue.
In the legacy implementation, the masking check was bypassed if UserInfo was empty:
// Legacy vulnerable masking logic in MaskedUri.cs
private static Uri Mask(Uri source)
{
if (string.IsNullOrEmpty(source.UserInfo))
{
return source; // Query parameters were skipped entirely
}
var builder = new UriBuilder(source)
{
UserName = "****",
Password = "****"
};
return builder.Uri;
}The updated implementation performs proactive masking of both UserInfo and sensitive query-string values through substring analysis:
// Patched logic in MaskedUri.cs
internal static Uri Mask(Uri source)
{
bool hasUserInfo = !string.IsNullOrEmpty(source.UserInfo);
string? maskedQueryString = MaskQueryString(source.Query);
if (!hasUserInfo && maskedQueryString == null)
{
return source;
}
var builder = new UriBuilder(source);
if (hasUserInfo)
{
builder.UserName = "****";
builder.Password = "****";
}
if (maskedQueryString != null)
{
builder.Query = maskedQueryString;
}
return builder.Uri;
}The MaskQueryString function parses the query components using HttpUtility.ParseQueryString and compares the keys against a pre-compiled array of sensitive terms (such as "pass", "pwd", "key", "token", "secret", "auth", "hash", "sig"). If any query key contains one of these terms, its value is immediately overwritten with asterisks.
Exploiting this vulnerability requires specific configuration and active network traffic but no prior user privileges. An attacker first scans the application surface to confirm the presence of Steeltoe actuator interfaces. If /actuator/httpexchanges is exposed, the attacker can verify if query-string recording is active.
During normal operation, legitimate clients perform activities that transmit short-lived or permanent credentials over the URL, such as password reset routines (/reset?token=XYZ), API gateway calls (/api?api_key=XYZ), or OAuth 2.0 redirection flows containing authorization codes. When these requests are processed by the server, the unsanitized URIs are logged directly into the application's memory storage buffer.
To retrieve the captured parameters, the attacker sends a standard GET request to the exchanges actuator endpoint:
GET /actuator/httpexchanges HTTP/1.1
Host: target.internal.netThe target application responds with a JSON payload containing transaction records. The attacker parses the returned request.uri entries to extract operational keys. Armed with these credentials, the attacker can perform account takeover, session hijacking, or escalate privileges within administrative APIs.
While the sanitization patch introduced in version 4.3.0 mitigates the immediate credential exposure risk, security teams should remain aware of potential bypass paths. The masking mechanism relies on a static, predefined blacklist of query key substrings. If developers transmit credentials using atypical parameter names that do not match the blacklist (such as ?id=, ?session=, or custom, company-specific keys), the values will pass through unsanitized.
Additionally, this logic only sanitizes URL query parameters. If credentials are split into standard RESTful path components (such as /api/v1/auth/session-abc1234/profile) rather than query arguments, the path-cleansing routine will not isolate or mask them. This limitation means path-based session tokens remain exposed to memory capturing and downstream log analysis.
Organizations must also ensure that POST and PUT body fields are handled securely, as the HttpExchanges actuator sanitization does not inspect request request bodies. For robust operational security, endpoints handling sensitive transaction states should migrate authentication metadata entirely to HTTP headers.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Steeltoe.Management.Endpoint SteeltoeOSS | < 4.3.0 | 4.3.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-200, CWE-532 |
| Attack Vector | Network |
| CVSS v3.1 Score | 5.9 (Medium) |
| Exploit Status | poc |
| CISA KEV Status | No |
| Attack Complexity | High |
| Impact | High (Information Disclosure) |
The product exposes sensitive information to an actor who is not authorized to have access to that information.
CVE-2026-76461 is a critical, unauthenticated, remotely exploitable SQL Injection (SQLi) vulnerability in the email parsing engine of Cisco AsyncOS Software for Cisco Secure Email Gateway (SEG). An unauthenticated remote attacker can exploit this vulnerability by transmitting a specially crafted email message containing malicious SQL statements directly through an affected gateway.
CVE-2026-72819 is a high-severity Remote Code Execution (RCE) vulnerability in Grav CMS before version 2.0.13. The vulnerability lies in the validation of dynamic data providers (callbacks) within the Flex Objects plugin settings and blueprints, allowing administrative users to bypass validation checks via array-notation callables. This validation failure enables administrative users to execute arbitrary PHP classes and methods, including the GPM Installer unZip routine, leading to full remote code execution on the server.
A logic verification vulnerability in `@libp2p/peer-store` (part of the `js-libp2p` ecosystem) allows unauthenticated remote attackers to bypass identity verification and poison a victim node's peer store database with arbitrary network multiaddresses. This occurs because `consumePeerRecord()` fails to ensure that the signature's identity matches the inner record payload's identity.
Improper neutralization of input during web page generation in Grav CMS allows authenticated users with page modification privileges to execute stored Cross-Site Scripting (XSS) attacks. The flaw exists in AudioMediaTrait and VideoMediaTrait where media source URLs are concatenated directly into HTML templates without proper escaping.
A directory traversal vulnerability exists in the Junrar archive extraction library prior to version 7.6.1. When extracting crafted RAR archives, the library allows unauthorized directory creation outside the designated destination root due to improper path normalization during directory creation.
CVE-2026-63506 is a critical authorization bypass vulnerability in TinaCMS self-hosted backend authentication packages (@tinacms/auth and next-tinacms-azure). By exploiting a request-controlled clientID parameter, unauthenticated attackers with an active token for any developer-registered TinaCloud application can bypass tenant boundaries and execute unauthorized administrative operations, including full GraphQL database interactions and arbitrary media management.