fix(ui): escape metric names, label values, and flag fuzzy output in React UI (CVE-2026-40179, CVE-2026-44903, CVE-2026-44990)#336
Merged
Conversation
…0179, CVE-2026-44903) Backports upstream prometheus/prometheus#18506 (GHSA-vffh-x6r8-xx99 / CVE-2026-40179) and prometheus/prometheus#18588 (GHSA-fw8g-cg8f-9j28 / CVE-2026-44903) for the React web UI we still ship. Affected sinks now call escapeHTML before interpolation into innerHTML: - Graph tooltips: __name__ and label keys (GraphHelpers.ts) - Metrics Explorer fuzzy search: escapeHTML option on Fuzzy - Heatmap bucket tooltip: le label (jquery.flot.heatmap.js) - Heatmap y-axis tick labels: le label (Graph.tsx) This blocks stored XSS in the Prometheus UI from metric names/label values ingested via scrape, remote-write or OTLP receivers when UTF-8 metric/label names allow <, > and " characters. Co-authored-by: Cursor <[email protected]>
…-44990) Defense-in-depth for GHSA-rpr9-rxv7-x643 (sanitize-html xmp raw-text passthrough), for which no upstream patch is released yet. The Flags page renders fuzzy-search results through sanitize-html with allowedTags=['strong']. Under the default config sanitize-html preserves the content of disallowed <xmp> tags verbatim, so a flag value containing <xmp>...</xmp> would survive sanitization. Set escapeHTML: true on the Fuzzy instance (same pattern we just used in MetricsExplorer for CVE-2026-40179) so the search output is fully entity-encoded except for the <strong> match markers. sanitize-html then sees only the strong tags plus harmless entity-encoded text and the xmp bypass is unreachable. Co-authored-by: Cursor <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Backports three Prometheus React-UI XSS fixes to our fork, plus a defense-in-depth workaround for an unpatched
sanitize-htmlbypass:sanitize-htmlxmpraw-text bypass) — no upstream patch yet, so we eliminate the only place we feed unescaped markup intosanitize-html(the Flags page).With Prometheus 3.x UTF-8 metric/label names, characters like
<,>,\"are valid in metric and label values. An attacker who can inject metrics (compromised scrape target, remote-write, or OTLP receiver) can land stored XSS in any UI user's browser. From the XSS context, depending on enabled flags, the attacker can read/api/v1/status/config, hit/-/quitor/api/v1/admin/tsdb/delete_series, or exfiltrate metric data.Prompp ships only the React UI (no Mantine UI), and we do not gate it behind
--enable-feature=old-ui, so the React UI is always served and these vulnerabilities are reachable here.Dependabot alerts that the same advisories map to in this repo: #177, #178, #187, #188, #192. The first four are pinned to `pp/tools/block_converter/go.mod` and `documentation/examples/remote_storage/go.mod` and don't actually use the vulnerable UI code paths — those alerts will need to be dismissed as `not used` after this PR ships the real fix. The sanitize-html alert (#192) is on the live npm tree but the only sink is now defanged by escaping upstream of the sanitizer.
Changes (each is a direct backport or a defense-in-depth tweak)
The pre-existing `escapeHTML()` helper in `web/ui/react-app/src/utils/index.ts` escapes `& < > " ' /`.
Test plan