CVE-2026-40179 Overview
CVE-2026-40179 is a stored cross-site scripting (XSS) vulnerability [CWE-79] affecting the Prometheus open-source monitoring system and time series database. The flaw exists in multiple components of the Prometheus web UI, where metric names and label values are injected into innerHTML without escaping. Affected versions include Prometheus 3.0 through 3.5.1 and 3.6.0 through 3.11.1. The vulnerability is triggered when a Prometheus user views a graph containing attacker-controlled metric names or labels. Prometheus v3.x defaults to UTF-8 metric and label name validation, allowing characters such as <, >, and " in metric identifiers. The issue was fixed in versions 3.5.2 and 3.11.2.
Critical Impact
Attackers who can inject metrics via a compromised scrape target, remote write, or OTLP receiver can execute arbitrary JavaScript in any user's browser viewing the Graph UI, enabling configuration exfiltration, data deletion, or Prometheus shutdown depending on enabled flags.
Affected Products
- Prometheus 3.0 through 3.5.1
- Prometheus 3.6.0 through 3.11.1
- Prometheus web UI components (Mantine UI and legacy React UI)
Discovery Timeline
- 2026-04-15 - CVE-2026-40179 published to NVD
- 2026-04-22 - Last updated in NVD database
Technical Details for CVE-2026-40179
Vulnerability Analysis
The vulnerability stems from unsafe rendering of user-controllable data in the Prometheus web UI. Chart tooltips on the Graph page in both the Mantine UI and the legacy React UI render metric names containing HTML and JavaScript without sanitization. In the legacy React UI, the Metric Explorer fuzzy search results use React's dangerouslySetInnerHTML without escaping inputs. Heatmap cell tooltips also interpolate le label values without sanitization.
Because Prometheus v3.x adopts UTF-8 validation by default for metric and label names, characters previously restricted such as <, >, and " are now valid identifiers. Stored payloads persist within the time series database and execute when any authenticated operator renders the affected views.
Root Cause
The root cause is missing output encoding when constructing HTML strings from metric names and label values. Affected helper functions in web/ui/mantine-ui/src/pages/query/uPlotChartHelpers.ts and web/ui/react-app/src/pages/graph/GraphHelpers.ts concatenated label keys and the __name__ label directly into template strings assigned to innerHTML.
Attack Vector
An attacker injects malicious metric names or label values through any ingestion path: a compromised scrape target, the remote write receiver (--web.enable-remote-write-receiver), or the OTLP receiver (--web.enable-otlp-receiver). When a Prometheus user later opens a graph or metric explorer that surfaces the poisoned series, the payload executes in the operator's browser session. If the admin API (--web.enable-admin-api) or lifecycle API (--web.enable-lifecycle) is enabled, the attacker can leverage the session to delete time series data or shut down the Prometheus instance.
// Security patch in web/ui/react-app/src/pages/graph/GraphHelpers.ts
const formatLabels = (labels: { [key: string]: string }): string => `
<div class="labels">
${Object.keys(labels).length === 0 ? '<div class="mb-1 font-italic">no labels</div>' : ''}
- ${labels['__name__'] ? `<div class="mb-1"><strong>${labels['__name__']}</strong></div>` : ''}
+ ${labels['__name__'] ? `<div class="mb-1"><strong>${escapeHTML(labels['__name__'])}</strong></div>` : ''}
${Object.keys(labels)
.filter((k) => k !== '__name__')
- .map((k) => `<div class="mb-1"><strong>${k}</strong>: ${escapeHTML(labels[k])}</div>`)
+ .map((k) => `<div class="mb-1"><strong>${escapeHTML(k)}</strong>: ${escapeHTML(labels[k])}</div>`)
.join('')}
</div>`;
-<span>${labels.__name__ || 'value'}: <strong>${yval}</strong></span>
+<span>${labels.__name__ ? escapeHTML(labels.__name__) : 'value'}: <strong>${yval}</strong></span>
Source: Prometheus security patch commit 07c6232. The fix wraps every label key and value, including the __name__ series identifier, with escapeHTML() before interpolation into template strings.
Detection Methods for CVE-2026-40179
Indicators of Compromise
- Metric names or label values containing HTML control characters such as <, >, ", ', or substrings like <script, onerror=, javascript:.
- Unexpected outbound HTTP requests originating from operator browsers shortly after viewing the Prometheus Graph UI.
- Unauthorized invocations of /api/v1/admin/tsdb/delete_series or /-/quit endpoints correlated with operator browser sessions.
- PromQL queries referencing label_replace in URLs shared from untrusted sources.
Detection Strategies
- Query the Prometheus /api/v1/label/__name__/values and /api/v1/labels endpoints and alert on label names or values containing HTML metacharacters.
- Inspect remote write and OTLP ingest logs for series whose identifiers fail strict legacy regex [a-zA-Z_:][a-zA-Z0-9_:]*.
- Review browser console errors and Content Security Policy violation reports from clients accessing the Prometheus UI.
Monitoring Recommendations
- Track the Prometheus server version and flag any instance running 3.0–3.5.1 or 3.6.0–3.11.1.
- Audit which flags are enabled, particularly --web.enable-remote-write-receiver, --web.enable-otlp-receiver, --web.enable-admin-api, and --web.enable-lifecycle.
- Monitor authentication and network reachability of scrape targets to identify compromised exporters that could push poisoned metrics.
How to Mitigate CVE-2026-40179
Immediate Actions Required
- Upgrade Prometheus to version 3.5.2 or 3.11.2, which contain the escapeHTML() fix.
- Restrict network exposure of the remote write receiver and OTLP receiver to trusted ingestion sources only.
- Disable the admin and lifecycle APIs in environments where untrusted metric data may be ingested.
- Review existing time series for label names or values containing HTML metacharacters and purge poisoned series.
Patch Information
The vulnerability is resolved in Prometheus 3.5.2 and 3.11.2. The upstream fix is published in Prometheus Pull Request #18506 and described in GitHub Security Advisory GHSA-vffh-x6r8-xx99. The remediation applies escapeHTML() to all label keys, label values, and the __name__ identifier before they are interpolated into UI templates.
Workarounds
- Ensure --web.enable-remote-write-receiver and --web.enable-otlp-receiver are not exposed to untrusted sources.
- Verify that all scrape targets are trusted and not under attacker control.
- Avoid enabling --web.enable-admin-api or --web.enable-lifecycle where untrusted data may be ingested.
- Refrain from clicking untrusted Prometheus links, particularly those containing label_replace, which can generate poisoned label names and values.
# Recommended hardened startup flags for Prometheus
prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/var/lib/prometheus \
--web.listen-address=127.0.0.1:9090 \
--web.external-url=https://prometheus.internal.example.com \
# Do NOT enable the following in untrusted environments:
# --web.enable-remote-write-receiver
# --web.enable-otlp-receiver
# --web.enable-admin-api
# --web.enable-lifecycle
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


