Mar 1, 2026·7 min read·95 visits
Unsanitized input reflection in go-httpbin allows attackers to force a text/html Content-Type response containing malicious JavaScript. Patched in version 2.18.0.
A reflected Cross-Site Scripting (XSS) vulnerability exists in mccutchen/go-httpbin (also known as httpbingo) versions prior to 2.18.0. The vulnerability allows remote attackers to execute arbitrary JavaScript in the context of a victim's browser by manipulating the 'Content-Type' header and response body content simultaneously. This issue affects endpoints designed to echo request data, such as /response-headers and /base64, where proper output encoding was not enforced for dangerous content types.
The go-httpbin library, a Go port of the popular httpbin.org service, is widely used by developers to test HTTP requests and responses. The service includes endpoints specifically designed to echo back data provided by the client, allowing users to inspect how their HTTP clients handle various server responses. However, versions prior to 2.18.0 contain a critical logic flaw in how these echo responses are generated, leading to Reflected Cross-Site Scripting (XSS).
The vulnerability, identified as CVE-2025-45286, arises from the application's willingness to accept a user-defined Content-Type via query parameters or path segments while simultaneously reflecting user input in the response body. By default, the application did not differentiate between safe content types (like application/json) and executable content types (like text/html).
When an attacker crafts a request that sets the Content-Type to text/html and injects HTML tags into the response body parameters, the browser interprets the server's output as an HTML document rather than a JSON object or plain text. This causes the browser to parse and execute any JavaScript embedded within the response, bypassing standard same-origin protections and granting the attacker execution context within the victim's session.
The root cause of this vulnerability is the failure to neutralize output based on the response context (CWE-79). Specifically, the /response-headers and /base64 endpoints in go-httpbin function as sinks that reflect untrusted input without adequate encoding when dangerous Multipurpose Internet Mail Extensions (MIME) types are specified.
In the /response-headers endpoint, the application iterates through provided query parameters to construct the HTTP response headers. Crucially, if a user provides a Content-Type parameter, the application applies it to the response header. After setting the headers, the application serializes the entire map of query parameters into a JSON object and writes it to the response body. The code implicitly assumed that because the body structure was JSON, it would be treated as data. However, browsers prioritize the Content-Type header over the body structure. If the header declares text/html, the browser attempts to render the JSON text as HTML, executing valid tags found within the JSON strings.
Similarly, the /base64 endpoint decodes a URL-provided base64 string and writes the raw bytes to the response. It also accepts a Content-Type override. An attacker can encode a malicious HTML payload in base64, append a Content-Type override, and force the server to serve a valid HTML page containing the payload. In both cases, the lack of an allowlist for content types or conditional HTML escaping for dangerous types facilitated the execution of arbitrary code.
The following analysis compares the vulnerable implementation with the remediated code in version 2.18.0. The focus is on the responseHeaders handler, which processes user input to generate headers and body content.
In the vulnerable version, the handler iterates over query parameters, sets them as headers, and then encodes the map directly to the response writer. No check exists to determine if the Content-Type is dangerous.
// Pre-patch logic (simplified)
func (h *Handler) responseHeaders(w http.ResponseWriter, r *http.Request) {
// ... (logic to parse params)
// 1. User input sets Content-Type header directly
for k, v := range params {
w.Header().Set(k, v[0])
}
// 2. User input is written to body as JSON
// If Content-Type is text/html, browser executes scripts in JSON strings
encoder := json.NewEncoder(w)
encoder.Encode(params)
}The fix introduces a safety check using mustEscapeResponse. If the requested Content-Type is not in a safe allowlist (e.g., application/json, text/plain), the application HTML-escapes the body content before writing it. This neutralizes <script> tags by converting them to <script>.
// Post-patch logic (Commit 0decfd1)
func (h *Handler) responseHeaders(w http.ResponseWriter, r *http.Request) {
contentType := getContentType(params)
// 1. Check if the requested content type requires escaping
if h.mustEscapeResponse(contentType) {
// 2. Use a buffer to encode the JSON first
var buf bytes.Buffer
json.NewEncoder(&buf).Encode(params)
// 3. HTML Escape the entire body string before writing
w.Write([]byte(html.EscapeString(buf.String())))
} else {
// Safe content types (json/plain) processed normally
json.NewEncoder(w).Encode(params)
}
}The patch also defines safeContentTypes map including application/json, text/plain, and application/octet-string. Any type not in this list triggers the escaping logic.
Exploiting this vulnerability requires crafting a URL that sets the Content-Type to text/html and includes a JavaScript payload in a reflected parameter. This attack vector relies on the victim clicking a malicious link (Reflected XSS).
go-httpbin instance.The following URL demonstrates the attack against the /response-headers endpoint:
http://vulnerable-httpbin.com/response-headers?Content-Type=text/html&xss=<script>alert(document.domain)</script>Execution Flow:
Content-Type=text/html and sets the response header Content-Type: text/html.xss to the JSON map: {"xss": "<script>alert(document.domain)</script>", ...}.text/html header. It ignores the JSON syntax and scans for HTML tags.<script>... and executes the JavaScript payload.A similar attack works on the /base64 endpoint by encoding the payload <html><script>alert(1)</script></html> into Base64 strings and appending it to the URL path, effectively turning go-httpbin into a malicious file host.
The impact of this vulnerability is classified as Medium (CVSS 6.1) because it requires user interaction and does not directly compromise the server's infrastructure. However, the consequences for the client/victim can be significant depending on the context in which go-httpbin is deployed.
Confidentiality Impact (Low/High): If the vulnerable instance runs on a domain that shares cookies or local storage with sensitive applications (e.g., an internal testing subdomain test.corp.com sharing context with admin.corp.com), an attacker could steal session tokens or authentication credentials. The S:C (Scope: Changed) metric in CVSS 3.1 reflects this potential to impact other resources in the browser's security context.
Integrity Impact (Low): An attacker can modify the visual presentation of the page or perform actions on behalf of the user, such as submitting unauthorized requests to other services accessible from the victim's browser (CSRF via XSS).
Availability Impact (None): This vulnerability does not allow for denial of service or server-side resource exhaustion. The server continues to function normally while serving the malicious payload.
The vulnerability is addressed in go-httpbin version 2.18.0. The primary remediation strategy is to upgrade the library to this version or later. The patch enforces HTML escaping for any response where the Content-Type is not explicitly allowlisted as safe.
The patch introduces a configuration flag, UNSAFE_ALLOW_DANGEROUS_RESPONSES (or the command-line flag -unsafe-allow-dangerous-responses). This flag defaults to false. Administrators must ensure this flag remains disabled in production environments. Enabling this flag reverts the application to the vulnerable behavior, negating the security fix.
For environments where immediate patching is not feasible, the following mitigations are recommended:
/response-headers and /base64 containing Content-Type=text/html or other dangerous MIME types (e.g., image/svg+xml, text/xml).go-httpbin instance. A policy such as default-src 'none'; script-src 'self'; would prevent the execution of inline scripts injected via this vulnerability.go-httpbin instances to trusted internal networks or authenticated users via VPN/Zero Trust proxies, reducing the likelihood of a successful phishing attack.CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
go-httpbin mccutchen | < 2.18.0 | 2.18.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79 |
| CWE Name | Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') |
| CVSS v3.1 | 6.1 (Medium) |
| Attack Vector | Network (Reflected) |
| EPSS Score | 0.00012 (1.47%) |
| Exploit Status | PoC Available |
A resource consumption vulnerability exists in the Authlib joserfc Python library prior to version 1.7.5. When processing JSON Web Encryption (JWE) objects formatted using General JSON Serialization, the library fails to enforce an upper bound on the number of elements within the recipients array. An unauthenticated attacker can supply a JWE containing thousands of recipient entries targeting an RSA key management algorithm, forcing the server to perform an equivalent number of computationally expensive RSA private-key decryption operations per request and exhausting available CPU resources.
CVE-2026-119284 (GHSA-9pg5-8c7x-5hfx) is an uncontrolled resource consumption vulnerability (CWE-400) in the compact serialization deserialization routines of joserfc prior to version 1.7.6. The library enforced individual segment size limits only after invoking Python's bytes.split(b'.') on untrusted input tokens. By sending oversized compact JWS or JWE tokens, an unauthenticated remote attacker can force the Python interpreter to duplicate and allocate memory for every segment before size validation executes, resulting in memory exhaustion and an Endpoint Denial of Service (DoS).
An improper input validation vulnerability (CWE-20) exists in the Entity Syntax Tree (EST) JSON deserialization component of the Cedar Policy Language (`cedar-policy` and `@cedar-policy/cedar-wasm`). When parsing JSON-formatted policy templates that define `is ... in` scope constraints on `principal` or `resource`, the parser used wildcard pattern matching that ignored the provided slot identifier (`?principal` or `?resource`). This omission allows malformed JSON templates to bypass initial deserialization validation, resulting in either a runtime panic during template linking or inverted slot bindings that alter authorization outcomes.
The @eeacms/volto-chatbot package for Plone Volto contains an unauthenticated confused deputy vulnerability (CWE-862) in versions 2.0.3 and earlier. The package registers Express middleware on wildcard proxy routes (`**/_v1_da/**` and `**/_v1_ha/**`) without verifying client authentication or restricting target endpoints. When processing incoming HTTP requests, the middleware automatically attaches server-side administrative credentials before forwarding the requests to upstream Danswer (Onyx) or Halloumi (LLMGW) API servers. This allows unauthenticated network attackers to execute arbitrary administrative API calls against the backend infrastructure.
CVE-2026-9705 is an insufficient session expiration and authorization bypass vulnerability in Keycloak and Red Hat build of Keycloak. The vulnerability occurs in the OAuth 2.0 Dynamic Client Registration Management Protocol implementation, where the authentication handler fails to verify whether a target client is enabled before accepting requests authenticated with a previously issued Registration Access Token (RAT). Consequently, an actor possessing a valid RAT for an administratively disabled client can query, update, and re-enable the client configuration, restoring revoked access to realm resources.
CVE-2026-9800 is an authorization bypass vulnerability affecting the Keycloak Policy Enforcer (org.keycloak:keycloak-policy-enforcer), which is integrated into Red Hat build of Keycloak, Red Hat build of Quarkus, Red Hat Single Sign-On 7, and Red Hat JBoss Enterprise Application Platform Expansion Pack. The flaw stems from improper comparison logic in the PolicyEnforcer.isDefaultAccessDeniedUri method, which uses loose substring matching on the full raw request URI rather than exact, normalized path comparisons against the configured access-denied landing page. Consequently, an authenticated attacker possessing any valid low-privileged token can bypass role-based, scope-based, and User-Managed Access (UMA) policy evaluations by embedding the access-denied path segment into the URL path or query parameters.