diff --git a/web/ui/mantine-ui/src/pages/query/uPlotChartHelpers.ts b/web/ui/mantine-ui/src/pages/query/uPlotChartHelpers.ts index 816ddf7578..afb09bfb4b 100644 --- a/web/ui/mantine-ui/src/pages/query/uPlotChartHelpers.ts +++ b/web/ui/mantine-ui/src/pages/query/uPlotChartHelpers.ts @@ -76,7 +76,7 @@ const formatLabels = (labels: { [key: string]: string }): string => ` .filter((k) => k !== "__name__") .map( (k) => - `
${escapeHTML(k)}: ${escapeHTML(labels[k])}
` + `
${escapeHTML(k)}: ${escapeHTML(labels[k])}
`, ) .join("")} `; @@ -153,7 +153,7 @@ const tooltipPlugin = (useLocalTime: boolean, data: AlignedData) => {
${formatTimestamp(ts, useLocalTime)}
- ${labels.__name__ ? labels.__name__ + ": " : " "}${value} + ${labels.__name__ ? escapeHTML(labels.__name__) + ": " : " "}${value}
${formatLabels(labels)} `.trimEnd(); @@ -193,7 +193,7 @@ const autoPadLeft = ( u: uPlot, values: string[], axisIdx: number, - cycleNum: number + cycleNum: number, ) => { const axis = u.axes[axisIdx]; @@ -208,7 +208,7 @@ const autoPadLeft = ( // Find longest tick text. const longestVal = (values ?? []).reduce( (acc, val) => (val.length > acc.length ? val : acc), - "" + "", ); if (longestVal != "") { @@ -228,7 +228,7 @@ const onlyDrawPointsForDisconnectedSamplesFilter = ( u: uPlot, seriesIdx: number, show: boolean, - gaps?: null | number[][] + gaps?: null | number[][], ) => { const filtered = []; @@ -287,7 +287,7 @@ export const getUPlotOptions = ( useLocalTime: boolean, yAxisMin: number | null, light: boolean, - onSelectRange: (_start: number, _end: number) => void + onSelectRange: (_start: number, _end: number) => void, ): uPlot.Options => ({ width: width - 30, height: 550, @@ -314,7 +314,7 @@ export const getUPlotOptions = ( markers: { fill: ( _u: uPlot, - seriesIdx: number + seriesIdx: number, ): CSSStyleDeclaration["borderColor"] => // Because the index here is coming from uPlot, we need to subtract 1. Series 0 // represents the X axis, so we need to skip it. @@ -411,7 +411,7 @@ export const getUPlotOptions = ( // @ts-expect-error - uPlot doesn't have a field for labels, but we just attach some anyway. labels: r.metric, stroke: getSeriesColor(idx, light), - }) + }), ), ], hooks: { @@ -421,7 +421,7 @@ export const getUPlotOptions = ( const leftVal = self.posToVal(self.select.left, "x"); const rightVal = Math.max( self.posToVal(self.select.left + self.select.width, "x"), - leftVal + 1 + leftVal + 1, ); onSelectRange(leftVal, rightVal); @@ -441,7 +441,7 @@ export const getUPlotData = ( inputData: RangeSamples[], startTime: number, endTime: number, - resolution: number + resolution: number, ): uPlot.AlignedData => { const timeData: number[] = []; for (let t = startTime; t <= endTime; t += resolution) { diff --git a/web/ui/react-app/src/pages/graph/GraphHelpers.ts b/web/ui/react-app/src/pages/graph/GraphHelpers.ts index 21bb768f52..60b38d5ab0 100644 --- a/web/ui/react-app/src/pages/graph/GraphHelpers.ts +++ b/web/ui/react-app/src/pages/graph/GraphHelpers.ts @@ -118,10 +118,10 @@ export const getOptions = (stacked: boolean, useLocalTime: boolean): jquery.flot const formatLabels = (labels: { [key: string]: string }): string => `
${Object.keys(labels).length === 0 ? '
no labels
' : ''} - ${labels['__name__'] ? `
${labels['__name__']}
` : ''} + ${labels['__name__'] ? `
${escapeHTML(labels['__name__'])}
` : ''} ${Object.keys(labels) .filter((k) => k !== '__name__') - .map((k) => `
${k}: ${escapeHTML(labels[k])}
`) + .map((k) => `
${escapeHTML(k)}: ${escapeHTML(labels[k])}
`) .join('')}
`; @@ -129,7 +129,7 @@ export const getOptions = (stacked: boolean, useLocalTime: boolean): jquery.flot
${dateTime.format('YYYY-MM-DD HH:mm:ss Z')}
- ${labels.__name__ || 'value'}: ${yval} + ${labels.__name__ ? escapeHTML(labels.__name__) : 'value'}: ${yval}
${'seriesLabels' in both ? 'Trace exemplar:' : 'Series:'}
${formatLabels(labels)} diff --git a/web/ui/react-app/src/pages/graph/MetricsExplorer.tsx b/web/ui/react-app/src/pages/graph/MetricsExplorer.tsx index 1959fa8265..053c630f38 100644 --- a/web/ui/react-app/src/pages/graph/MetricsExplorer.tsx +++ b/web/ui/react-app/src/pages/graph/MetricsExplorer.tsx @@ -2,7 +2,7 @@ import React, { Component, ChangeEvent } from 'react'; import { Modal, ModalBody, ModalHeader, Input } from 'reactstrap'; import { Fuzzy, FuzzyResult } from '@nexucis/fuzzy'; -const fuz = new Fuzzy({ pre: '', post: '', shouldSort: true }); +const fuz = new Fuzzy({ pre: '', post: '', shouldSort: true, escapeHTML: true }); interface MetricsExplorerProps { show: boolean; diff --git a/web/ui/react-app/src/vendor/flot/jquery.flot.heatmap.js b/web/ui/react-app/src/vendor/flot/jquery.flot.heatmap.js index 29d5c81ef7..be21821fdd 100644 --- a/web/ui/react-app/src/vendor/flot/jquery.flot.heatmap.js +++ b/web/ui/react-app/src/vendor/flot/jquery.flot.heatmap.js @@ -6,6 +6,7 @@ See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3384 for more deta import moment from 'moment-timezone'; import {formatValue} from "../../pages/graph/GraphHelpers"; +import {escapeHTML} from '../../utils'; const TOOLTIP_ID = 'heatmap-tooltip'; const GRADIENT_STEPS = 16; @@ -82,7 +83,7 @@ const GRADIENT_STEPS = 16; tooltip.className = cssClass; const timeHtml = `
${dateTime.join('
')}
` - const labelHtml = `
Bucket: ${label || 'value'}
` + const labelHtml = `
Bucket: ${label ? escapeHTML(label) : 'value'}
` const valueHtml = `
Value: ${value}
` tooltip.innerHTML = `
${timeHtml}
${labelHtml}${valueHtml}
`;