CVE-2025-25304
Description
Vega is a visualization grammar, a declarative format for creating, saving, and sharing interactive visualization designs. Prior to version 5.26.0 of vega and 5.4.2 of vega-selections, the vlSelectionTuples function can be used to call JavaScript functions, leading to cross-site scripting.vlSelectionTuples calls multiple functions that can be controlled by an attacker, including one call with an attacker-controlled argument. This can be used to call Function() with arbitrary JavaScript and the resulting function can be called with vlSelectionTuples or using a type coercion to call toString or valueOf. Version 5.26.0 of vega and 5.4.2 of vega-selections fix this issue.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Vega and vega-selections prior to 5.26.0/5.4.2 contain an XSS vulnerability where the vlSelectionTuples function can call arbitrary JavaScript via attacker-controlled arguments.
Vulnerability
Overview
CVE-2025-25304 is a cross-site scripting (XSS) vulnerability in Vega, a declarative visualization grammar, and the separate vega-selections package. The flaw resides in the vlSelectionTuples function, which is used to process selection interactions. An attacker can control arguments passed to this function, triggering execution of arbitrary JavaScript. Specifically, vlSelectionTuples calls multiple functions that can be influenced by an attacker, including one call with an attacker-controlled argument. This can be exploited to invoke Function() with arbitrary code, and the resulting function can then be called via vlSelectionTuples or through type coercion to toString or valueOf. [1][4]
Exploitation
Method
To exploit the vulnerability, an attacker crafts a malicious Vega specification that passes a specially crafted object to vlSelectionTuples. For example, a call like vlSelectionTuples([{datum:}], {fields:[{getter:}]}) allows the attacker to control the getter function. By setting getter to [].at.constructor (i.e., Function), the attacker can execute arbitrary JavaScript. The provided proof-of-concept uses a signal with an init expression that coerces values through valueOf, leading to code execution. No authentication is required if the attacker can supply or modify a Vega specification. [2][4]
Impact
Successful exploitation allows an attacker to execute arbitrary JavaScript in the context of the user's browser when the visualization is rendered. This can lead to session hijacking, data exfiltration, or defacement. The vulnerability affects all Vega and vega-selections versions before the fixes.
Mitigation
The Vega team patched this issue in Vega version 5.26.0 and vega-selections version 5.4.2. Users should update to these or later versions immediately. There are no known workarounds. The vulnerability is not yet listed in CISA's Known Exploited Vulnerabilities catalog, but prompt patching is recommended. [3][4]
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
veganpm | < 5.26.0 | 5.26.0 |
vega-selectionsnpm | < 5.4.2 | 5.4.2 |
Affected products
4- ghsa-coords2 versions
< 5.26.0+ 1 more
- (no CPE)range: < 5.26.0
- (no CPE)range: < 5.4.2
Patches
23580b28ec9b89fb9ea07e279Merge pull request from GHSA-mp7w-mhcv-673j
5 files changed · +19 −9
packages/vega-selections/src/selectionResolve.js+1 −1 modified@@ -1,6 +1,6 @@ import {intersection, union} from 'd3-array'; import {array, toNumber} from 'vega-util'; -import {$selectionId, And, Or, SelectionId, Union, VlMulti, VlPoint} from './constants'; +import {$selectionId, And, Or, SelectionId, Union, VlMulti, VlPoint} from './util'; /** * Resolves selection for use as a scale domain or reads via the API.
packages/vega-selections/src/selectionTest.js+3 −4 modified@@ -1,6 +1,6 @@ import {bisector} from 'd3-array'; -import {$selectionId, Intersect} from './constants'; -import {field, inrange, isArray, isDate, toNumber} from 'vega-util'; +import {inrange, isArray, isDate, toNumber} from 'vega-util'; +import {$selectionId, Intersect, getter} from './util'; const TYPE_ENUM = 'E', TYPE_RANGE_INC = 'R', @@ -18,8 +18,7 @@ function testPoint(datum, entry) { for (; i<n; ++i) { f = fields[i]; - f.getter = field.getter || field(f.field); - dval = f.getter(datum); + dval = getter(f)(datum); if (isDate(dval)) dval = toNumber(dval); if (isDate(values[i])) values[i] = toNumber(values[i]);
packages/vega-selections/src/selectionTuples.js+3 −3 modified@@ -1,5 +1,5 @@ -import {extend, field} from 'vega-util'; -import {$selectionId, SelectionId} from './constants'; +import {extend} from 'vega-util'; +import {$selectionId, SelectionId, getter} from './util'; /** * Maps an array of scene graph items to an array of selection tuples. @@ -11,7 +11,7 @@ import {$selectionId, SelectionId} from './constants'; export function selectionTuples(array, base) { return array.map(x => extend( base.fields ? { - values: base.fields.map(f => (f.getter || (f.getter = field(f.field)))(x.datum)) + values: base.fields.map(f => getter(f)(x.datum)) } : { [SelectionId]: $selectionId(x.datum) }, base));
packages/vega-selections/src/selectionVisitor.js+1 −1 modified@@ -1,6 +1,6 @@ -import {Intersect} from './constants'; import {Literal} from 'vega-expression'; import {error, hasOwnProperty, peek} from 'vega-util'; +import {Intersect} from './util'; const DataPrefix = ':', IndexPrefix = '@';
packages/vega-selections/src/util.js+11 −0 renamed@@ -1,5 +1,16 @@ import {field} from 'vega-util'; +// Registers vega-util field accessors to protect against XSS attacks +const SELECTION_GETTER = Symbol('vega_selection_getter'); +export function getter(f) { + if (!f.getter || !f.getter[SELECTION_GETTER]) { + f.getter = field(f.field); + f.getter[SELECTION_GETTER] = true; + } + + return f.getter; +} + export const Intersect = 'intersect'; export const Union = 'union'; export const VlMulti = 'vlMulti';
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-mp7w-mhcv-673jghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-25304ghsaADVISORY
- github.com/vega/vega/blob/b45cf431cd6c0d0c0e1567f087f9b3b55bc236fa/packages/vega-selections/src/selectionTuples.jsnvdWEB
- github.com/vega/vega/commit/9fb9ea07e27984394e463d286eb73944fa61411envdWEB
- github.com/vega/vega/security/advisories/GHSA-mp7w-mhcv-673jnvdWEB
News mentions
0No linked articles in our index yet.