Feb 28, 2026·5 min read·83 visits
CVE-2025-66648 is a High-severity XSS vulnerability in Vega versions prior to 6.1.1. Attackers can execute arbitrary JavaScript by injecting a malicious signal handler that traverses the `event` object to access the global `window` context. This affects applications rendering untrusted Vega specifications.
A critical vulnerability exists in the `vega-functions` package, a core dependency of the Vega visualization grammar. The flaw permits attackers to escape the expression sandbox by leveraging object context leakage within signal handlers. Specifically, the `setdata` function (which utilizes the internal `modify` method) allows the execution of arbitrary JavaScript functions found via property traversal on the `event` object. This bypasses standard expression interpretation safeguards, including the 'CSP-safe' interpreter, enabling Cross-Site Scripting (XSS) when rendering user-supplied visualization specifications.
The Vega visualization grammar allows users to define interactive visualizations using a JSON specification. To support interactivity, Vega includes an expression language that evaluates logic within signal handlers. While Vega implements an expression interpreter to restrict execution to a safe subset of JavaScript, CVE-2025-66648 reveals a bypass in this sandbox mechanism located within the vega-functions component.
The vulnerability manifests in the setdata expression function, which is designed to modify data tuples dynamically. The flaw allows an attacker to manipulate the test predicate argument of the underlying modify function. By traversing properties available on the event object—specifically accessing the internal Dataflow graph and the DOM element—an attacker can reach the global window object. This effectively grants access to native browser APIs (e.g., fetch, alert) and enables arbitrary code execution in the context of the application rendering the chart.
The root cause is a combination of object context leakage and insufficient validation of function arguments within the internal modify() function. When a signal event triggers, Vega exposes an event object to the expression scope. This object inadvertently retains references to internal engine structures that should be opaque to the user.
Specifically, the event object links to the dataflow instance, which in turn holds a reference to the underlying DOM element (_el). From a DOM element, standard JavaScript property traversal allows access to ownerDocument and defaultView, effectively leaking the global window object. The modify(name, insert, remove, toggle, test, values) function failed to validate that its test argument was a safe, internal predicate. Instead, it accepted any function reference passed to it and executed that function against data tuples during the dataflow propagation cycle.
The vulnerability lies in how vega-functions handles arguments passed to the setdata (and underlying modify) function without scrutinizing the origin of the predicate function. Below is a conceptual representation of the vulnerable logic versus the patched approach.
The unpatched version allowed the test parameter to be any callable function derived from the expression scope, including those reachable via the prototype chain or object traversal.
// Conceptual vulnerable implementation in vega-functions
function modify(name, insert, remove, toggle, test, values) {
// ... lookup dataset by name ...
// The 'test' function is invoked directly without verifying it is safe
if (test && test(tuple)) {
// modify tuple
}
}The fix introduces strict validation to ensure arguments are expected types and blocks access to sensitive internal properties like _el on the dataflow object. The patch likely sanitizes the event object before exposing it to the expression scope or explicitly validates that the test function is a generated internal predicate rather than a user-supplied reference to window methods.
// Conceptual patched implementation
function modify(name, insert, remove, toggle, test, values) {
// Validation: Ensure 'test' is not a native function or external reference
if (test && !isInternalPredicate(test)) {
throw new Error("Illegal argument to setdata");
}
// Hardening: The 'event' object passed to expressions no longer exposes '_el'
// event.dataflow._el => undefined
}Exploitation requires the attacker to supply a malicious Vega JSON specification to a target application. The payload leverages a signal handler listening for standard user interaction events (like click or mouseover) to trigger the execution chain.
The attacker constructs a setdata call that walks the property chain from event to window. The payload demonstrates executing alert(), but a real-world attack would likely use fetch() to exfiltrate tokens or eval() (if CSP permits) to execute complex payloads.
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"signals": [
{
"name": "triggerXSS",
"on": [
{
"events": "click",
"update": "setdata('table', [], [], [], event.dataflow._el.ownerDocument.defaultView.alert('XSS'))"
}
]
}
],
"data": [
{ "name": "table", "values": [{"id": 1}] }
]
}> [!WARNING]
> CSP Safe Mode Bypass: This vulnerability bypasses vega.expressionInterpreter. Even if an application explicitly uses the interpreter to avoid eval() and adhere to Content Security Policy, this specific vector succeeds because it relies on existing function references (window.alert) rather than string-to-code compilation.
The impact of this vulnerability is high (CVSS 7.2) because it allows for Stored XSS or Reflected XSS depending on how the application loads Vega specifications.
Confidentiality: Attackers can read sensitive data from the DOM, including session cookies (if not HttpOnly), LocalStorage tokens, and CSRF tokens.
Integrity: Attackers can modify the visual content of the dashboard to mislead users or inject phishing forms overlaying the legitimate application interface.
Scope: This affects any system integrating Vega or Vega-Lite where users can save or share visualizations. Common targets include data science notebooks (Jupyter), business intelligence dashboards (Kibana), and wiki-style documentation systems integrating Vega rendering.
The only effective remediation is to upgrade the vulnerable dependencies.
vega-functions6.1.1vega (Fixed in 5.30.0 or equivalent depending on dependency tree resolution)Developers should verify their lockfiles (package-lock.json or yarn.lock) to ensure that transitive dependencies of vega are resolved to vega-functions version 6.1.1 or higher. No configuration changes or workarounds are available; the code itself must be patched to prevent the context leakage.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
vega-functions Vega Project | < 6.1.1 | 6.1.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79 |
| Attack Vector | Network |
| CVSS v3.1 | 7.2 (High) |
| EPSS Score | 0.00045 |
| Exploit Maturity | Proof-of-Concept |
| Impact | Arbitrary Code Execution (Browser Context) |
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Grav CMS prior to version 1.7.53 and 2.0.0-rc.8 is vulnerable to an unauthenticated remote denial of service (DoS) vulnerability. By supplying crafted query parameters with extremely large dimensions to image assets, remote unauthenticated attackers can force the server to allocate massive amounts of system memory, leading to kernel Out-Of-Memory (OOM) termination of web worker processes.
CVE-2026-53657 is a local privilege escalation vulnerability in Lima (lima-vm/lima) affecting versions prior to 2.1.3 when configured with the QEMU driver. The guest agent daemon, running as root, creates its communication socket `/run/lima-guestagent.sock` with world-writable permissions (0777). This allows unprivileged local users to command the agent to establish arbitrary tunnels, including to privileged local UNIX sockets (like D-Bus). Because the target daemon authenticates the incoming connection using the credentials of the root-owned guest agent (via SO_PEERCRED), unprivileged users can perform root operations, resulting in complete guest VM compromise.
An unauthenticated Denial of Service vulnerability exists in the s2n-quic library's CryptoStream reassembler due to a lack of buffer limits on out-of-order cryptographic frames. An attacker can transmit a crafted CRYPTO frame with an extremely high offset and nominal payload, forcing the receiver to execute unbounded memory allocations and causing service crashes.
A JNDI Injection and Deserialization Gadget vulnerability exists in mchange-commons-java prior to version 0.6.0. The com.mchange.v2.naming.JavaBeanObjectFactory component permits arbitrary class instantiation and setter invocation, allowing attackers to perform Server-Side Request Forgery (SSRF) and remote class loading.
SurrealDB versions supporting element-level SELECT permissions on arrays are vulnerable to a logical authorization bypass. Due to an index-shifting error during array filtration, restricted elements can skip permission checks and leak to unauthorized record users.
CVE-2026-12243 is a path traversal vulnerability in the Natural Language Toolkit (NLTK) version 3.9.4. The flaw exists because the input validation routine fails to account for percent-encoded directory traversal sequences like '..%2f' before passing them to urllib.request.url2pathname(), which decodes them into active traversal sequences.