CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-528Q-4PGM-WVG2
6.10.01%

CVE-2025-45286: Reflected Cross-Site Scripting (XSS) in go-httpbin

Alon Barad
Alon Barad
Software Engineer

Mar 1, 2026·6 min read·1 visit

PoC Available

Executive Summary (TL;DR)

Unsafe reflection of user input in `go-httpbin` allows XSS via crafted `Content-Type` headers. Attackers can execute arbitrary scripts by tricking users into visiting malicious links targeting endpoints like `/response-headers`. Fixed 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 arises from improper neutralization of user-supplied input in endpoints that reflect data back to the client, such as `/response-headers` and `/base64`. Attackers can manipulate the `Content-Type` response header to force the browser to interpret the response body as HTML, allowing for the execution of arbitrary JavaScript in the context of the victim's session.

Vulnerability Overview

mccutchen/go-httpbin is a robust Go implementation of the popular httpbin service, designed to test HTTP clients by echoing request data and simulating various HTTP behaviors. The service exposes multiple endpoints, including /response-headers (which echoes query parameters as response headers) and /base64 (which decodes and reflects base64-encoded data). These endpoints are intended to be flexible tools for developers debugging network interactions.

The vulnerability, identified as CVE-2025-45286, is a Reflected Cross-Site Scripting (XSS) flaw classified under CWE-79 (Improper Neutralization of Input During Web Page Generation). It occurs because the application allows clients to strictly control both the Content-Type of the response and the content of the response body without adequate validation or encoding.

When a victim visits a crafted URL pointing to a vulnerable go-httpbin instance, the server reflects the attacker's payload in the HTTP response body. Crucially, the attacker can also override the Content-Type header to text/html. This instructs the victim's browser to parse the reflected data as an HTML document rather than its intended format (such as JSON or plain text), triggering the execution of embedded malicious scripts.

Root Cause Analysis

The root cause of this vulnerability is the combination of unrestricted header injection and the lack of output encoding for reflected data. In a secure web application, user input reflected in the response body must be contextually encoded (e.g., HTML entity encoding) to prevent interpretation as executable code. Additionally, allowing users to arbitrarily set the Content-Type header enables the browser's HTML parser to process the reflected input.

Specifically, the /response-headers endpoint iterates over provided query parameters and sets them as HTTP response headers. It then constructs a JSON representation of these headers and writes it to the response body. Prior to version 2.18.0, the application did not sanitize the keys or values written to the JSON body. If an attacker supplied ?Content-Type=text/html, the browser would receive a response declaring itself as HTML.

Simultaneously, the body content—derived from the query parameters—contains the raw, unescaped input. For example, if the parameter includes <script>alert(1)</script>, this string is written directly into the response. Because the content type is text/html, the browser ignores the JSON structure surrounding the string and executes the script tag immediately upon parsing. The same logic applies to the /base64 endpoint, which decodes arbitrary input and writes it to the response stream, relying on the user-controlled Content-Type to determine how it is rendered.

Code Analysis

The remediation for CVE-2025-45286 introduces a strict allowlist for content types and enforces HTML escaping for any type not on that list. The fix was applied in commit 0decfd1a2e88d85ca6bfb8a92421653f647cbc04.

Vulnerable Logic (Conceptual): Previously, the handler blindly accepted the content type and wrote the raw value:

// Pseudo-code of vulnerable behavior
w.Header().Set("Content-Type", userProvidedContentType)
// ...
json.NewEncoder(w).Encode(headers) // Writes raw strings inside JSON

Patched Logic: The patch introduces a safeContentTypes map and a mustEscapeResponse helper function. The safeContentTypes allowlist includes text/plain, application/json, and application/octet-string. If a user requests a Content-Type not in this list (e.g., text/html), the application forces HTML escaping on the output.

// From commit 0decfd1a2e88d85ca6bfb8a92421653f647cbc04
 
var safeContentTypes = map[string]bool{
    "text/plain":               true,
    "application/json":         true,
    "application/octet-string": true,
}
 
// In the handler logic:
contentType := r.URL.Query().Get("Content-Type")
shouldEscape := !safeContentTypes[contentType] && !s.UnsafeAllowDangerousResponses
 
for key, values := range headers {
    for i, val := range values {
        if shouldEscape {
            // Crucial Fix: Escape the value if the content type is dangerous
            values[i] = html.EscapeString(val)
        }
    }
}

This change ensures that even if an attacker forces a text/html header, the payload <script> will be rendered as &lt;script&gt;, effectively neutralizing the XSS attack. The patch also adds a configuration flag UnsafeAllowDangerousResponses to opt-out of this protection, maintaining backward compatibility for users who strictly require the old behavior.

Exploitation Methodology

Exploitation requires the attacker to construct a URL that sets the Content-Type to text/html and includes a JavaScript payload. The victim must then be tricked into clicking this link (e.g., via phishing or a redirect).

Scenario 1: /response-headers Endpoint The attacker targets the header reflection mechanism. The payload is passed as a value for a dummy header.

  • URL: http://target-httpbin/response-headers?Content-Type=text/html&X-Payload=<script>alert(origin)</script>
  • Mechanism: The server sets Content-Type: text/html and prints a JSON body containing {"X-Payload": ["<script>alert(origin)</script>"]}. The browser executes the script.

Scenario 2: /base64 Endpoint The attacker encodes the XSS payload in Base64 and passes the content type as a query parameter.

  • Payload: <img src=x onerror=alert(1)> -> Base64: PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==
  • URL: http://target-httpbin/base64/PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==?content-type=text/html
  • Mechanism: The server decodes the path and echoes it back with the requested content type. The browser renders the malicious <img> tag.

Impact Assessment

The impact of this vulnerability is typical of Reflected XSS, rated as Medium (CVSS 6.1). While go-httpbin is often deployed in testing environments, it is frequently accessible internally by developers or exposed publicly for demonstration purposes.

Confidentiality Impact: An attacker can execute scripts to read sensitive data accessible to the browser in the context of the go-httpbin domain. This could include session cookies (if any exist on that domain), local storage, or sensitive data displayed on other pages within the same origin.

Integrity Impact: The attacker can modify the DOM of the page, potentially displaying false information or redirecting the user to a malicious site. In a development environment, this could be used to trick a developer into downloading malicious tools or credential harvesting.

Scope: The vulnerability allows the attacker to pivot from the vulnerable application to the user's browser context (Scope: Changed). The requirement for user interaction (UI: Required) limits the severity slightly, as the attack cannot be automated without user participation.

Remediation & Mitigation

The primary remediation is to upgrade the affected software to a patched version.

Official Patch: Upgrade mccutchen/go-httpbin to version 2.18.0 or later. This version is available on GitHub and standard package repositories.

Configuration Review: After upgrading, ensure that the application is not launched with the -unsafe-allow-dangerous-responses flag or the UNSAFE_ALLOW_DANGEROUS_RESPONSES environment variable set to true. Enabling this flag reverts the security fix and re-exposes the application to XSS attacks.

Workarounds: If an immediate upgrade is not feasible, implement a reverse proxy (e.g., Nginx, AWS WAF) in front of the application to strip or sanitize incoming requests containing Content-Type=text/html query parameters, or to override the response Content-Type header to application/json regardless of the query parameter value.

Official Patches

GitHubCommit fixing the XSS by escaping dangerous content

Fix Analysis (1)

Technical Appendix

CVSS Score
6.1/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
EPSS Probability
0.01%
Top 99% most exploited

Affected Systems

mccutchen/go-httpbin (httpbingo) < 2.18.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
go-httpbin
mccutchen
< 2.18.02.18.0
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork
CVSS6.1 (Medium)
EPSS0.00012 (1.47%)
ImpactReflected XSS
Exploit StatusProof of Concept

MITRE ATT&CK Mapping

T1059.007Command and Scripting Interpreter: JavaScript
Execution
T1189Drive-by Compromise
Initial Access
CWE-79
Cross-site Scripting

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Known Exploits & Detection

GitHub AdvisoryAdvisory containing PoC for /response-headers and /base64 endpoints

Vulnerability Timeline

Vulnerability published in NVD
2025-01-02
Fix commit merged
2025-03-20
GHSA Advisory Published
2026-01-02

References & Sources

  • [1]GHSA-528q-4pgm-wvg2
  • [2]NVD - CVE-2025-45286
  • [3]OSV - GO-2025-3554
Related Vulnerabilities
CVE-2025-45286

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.