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-FW8G-CG8F-9J28
6.50.04%

GHSA-FW8G-CG8F-9J28: Stored Cross-Site Scripting in Prometheus Legacy Web UI Heatmap

Amit Schendel
Amit Schendel
Senior Security Researcher

May 5, 2026·6 min read·5 visits

PoC Available

Executive Summary (TL;DR)

A stored XSS vulnerability in the Prometheus legacy web UI allows attackers to execute arbitrary JavaScript via maliciously crafted histogram bucket labels, affecting versions prior to 3.11.3.

Prometheus versions prior to 3.11.3 contain a Stored Cross-Site Scripting (XSS) vulnerability in the legacy web UI's heatmap visualization component. An attacker can inject arbitrary JavaScript by providing malicious `le` (less-than-or-equal) bucket labels within scraped metrics. When an administrator views the heatmap in the legacy UI, the payload executes within their browser context, potentially leading to unauthorized configuration access or actions performed on behalf of the user.

Vulnerability Overview

Prometheus is a widely deployed systems monitoring and alerting toolkit that collects and stores metrics as time-series data. The platform exposes a web-based user interface for querying and visualizing this data. A legacy version of this interface, often referred to as the 'Old UI', remains accessible in many deployments and contains a vulnerability within its heatmap visualization feature.

The vulnerability is classified as Stored Cross-Site Scripting (CWE-79). It specifically affects the rendering of histogram metrics. In the Prometheus data model, histograms track distributions of events using buckets, which are defined by an le (less-than-or-equal) label. The legacy UI processes these le labels to generate Y-axis ticks on heatmap charts.

An attacker can exploit this vulnerability by introducing a metric with a crafted le label into the Prometheus time-series database. When a victim subsequently queries this metric and generates a heatmap using the legacy UI, the malicious label is rendered without sanitization. This execution context allows the attacker's JavaScript to interact with the Prometheus web interface using the session privileges of the victim.

Root Cause Analysis

The root cause of this vulnerability lies in the improper neutralization of user-controllable input within the legacy UI's React components. Specifically, the flaw exists in the tickFormatter function for the Y-axis, located in web/ui/react-app/src/pages/graph/Graph.tsx. This function extracts the le label from the underlying metric data and returns it as a string to be rendered on the chart.

The legacy UI utilizes the Flot plotting library, a jQuery-based visualization tool. Unlike modern React rendering paradigms that inherently escape HTML entities, Flot often processes axis labels by directly injecting them into the Document Object Model (DOM) via methods such as .html(). This architectural choice shifts the responsibility of output encoding to the implementer.

The vulnerable implementation directly returns the raw string value of the le label. If the underlying time-series data contains HTML tags or JavaScript event handlers within this label, Flot parses and executes them during the chart rendering phase. The application implicitly trusts the structure and content of ingested metrics, failing to enforce a boundary between data and executable code at the presentation layer.

Code Analysis

An analysis of web/ui/react-app/src/pages/graph/Graph.tsx reveals the exact mechanism of the flaw and its remediation. The vulnerable implementation defines the tickFormatter inline within the chart configuration object. It retrieves the label array from the metric data structure and accesses the le key directly.

// Vulnerable Code Snippet in Graph.tsx
options.yaxis.tickFormatter = (val) => `${val ? data[val - 1].labels.le : ''}`;

The fix, introduced in commit 38f23b9075ced1de2b82d2dad8b2bebb1ecd5b7d, introduces an explicit output encoding step. The maintainers imported an existing escapeHTML utility function and wrapped the label extraction logic. This function converts characters with special meaning in HTML into their corresponding safe entities.

// Patched Code Snippet in Graph.tsx
import { escapeHTML } from '../../utils';
// ...
options.yaxis.tickFormatter = (val) => `${val ? escapeHTML(data[val - 1].labels.le) : ''}`;

By ensuring that characters such as < and > are converted to &lt; and &gt;, the Flot library is forced to treat the label strictly as text content rather than markup. This change comprehensively addresses the vulnerability within the heatmap component by neutralizing the payload immediately prior to presentation.

Exploitation

Exploitation requires the attacker to inject a malicious metric into the Prometheus database. This can be achieved through two primary vectors: exposing the payload on an endpoint scraped by Prometheus, or pushing the metric directly via the Prometheus Remote Write API. The attacker does not require direct access to the Prometheus web UI to stage the payload.

A viable proof-of-concept payload targets the histogram metric format. The attacker exposes a metric where the le label contains an image tag with an onerror event handler. The event handler executes the arbitrary JavaScript.

http_request_duration_seconds_bucket{le="<img src=x onerror=alert('XSS')>", method="GET"} 1

Once the metric is ingested, the vulnerability lies dormant until a user interacts with the data. An administrator or user must navigate to the 'Graph' page in the Old UI and execute a query that returns the malicious histogram bucket. As the UI attempts to draw the heatmap Y-axis ticks, the browser processes the <img> tag, fails to load the nonexistent source x, and fires the onerror event, triggering the payload.

Impact Assessment

The impact of this Stored XSS vulnerability is contingent upon the privileges of the victim and the network configuration of the Prometheus deployment. Because the payload executes in the context of the victim's session, the attacker inherits the victim's authentication state and interaction capabilities with the Prometheus interface.

Arbitrary JavaScript execution allows the attacker to silently issue API requests to the Prometheus server. This enables the exfiltration of sensitive monitoring data, including alerting rules, target configurations, and internal infrastructure topology exposed via metric labels. If the Prometheus instance is configured with administrative APIs enabled (e.g., the lifecycle or remote write administration endpoints), the attacker could manipulate server state.

Furthermore, if the victim is an infrastructure administrator accessing Prometheus from an internal, trusted network segment, the compromised browser context can serve as a pivot point. The attacker's script could initiate requests to other internal services accessible from the victim's machine, expanding the scope of the breach beyond the monitoring infrastructure.

Remediation

The primary remediation for this vulnerability is to upgrade the Prometheus server to version 3.11.3 or later. This release includes the necessary output encoding modifications in the legacy UI components. Organizations utilizing older release branches should check for backported fixes, specifically around the 3.5.3 release line, as noted in vendor advisories.

If immediate patching is not feasible, organizations can mitigate the risk by modifying their operational procedures to strictly avoid the Old UI. Administrators should instruct all personnel to utilize the modern React-based UI included in newer Prometheus versions, which is not susceptible to this specific flaw due to its native component rendering behavior. Additionally, external visualization platforms like Grafana securely handle metric label sanitization and can be used as a safe alternative.

As a defense-in-depth measure, administrators can employ metric relabeling rules within the Prometheus scrape configuration to sanitize or drop incoming metrics containing suspicious characters in label values. Dropping metrics where the le label contains HTML bracket characters (< or >) effectively prevents the payload from entering the time-series database entirely.

Official Patches

Prometheus ProjectOfficial Pull Request containing the fix for the XSS vulnerability.
Prometheus ProjectCommit implementing the escapeHTML mitigation.

Fix Analysis (1)

Technical Appendix

CVSS Score
6.5/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
EPSS Probability
0.04%
Top 85% most exploited
45,000
Estimated exposed hosts via Shodan

Affected Systems

Prometheus ServerPrometheus Legacy Web UI (Old UI)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Prometheus
Prometheus Project
< 3.11.33.11.3
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork / Stored Ingestion
CVSS Score6.5 (Moderate)
ImpactSession Hijacking, Configuration Theft
Exploit StatusProof of Concept
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059.007Command and Scripting Interpreter: JavaScript
Execution
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.

Known Exploits & Detection

Vulnerability ReportProof of concept payload utilizing an image tag with an onerror event handler injected into the 'le' label of a histogram metric.

Vulnerability Timeline

Patch Committed to Prometheus Repository
2026-04-22
Public Disclosure and Prometheus v3.11.3 Release
2026-04-27

References & Sources

  • [1]GitHub Security Advisory: GHSA-FW8G-CG8F-9J28
  • [2]Prometheus Pull Request #18588
  • [3]Prometheus Fix Commit 38f23b9
  • [4]Prometheus Release Notes

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.