Page MenuHomePhabricator

CVE-2026-39837: Stored XSS through the dynamic table format in Cargo
Closed, ResolvedPublicSecurity

Description

The script for the dynamic table format in Cargo retrieves HTML from a non-reserved data attribute, allowing for stored XSS since those data attributes can be used in wikitext.

Reproduction steps

  1. Create or preview a page with the following contents:
<div style="display:none">{{#cargo_query:
|tables=Authors
|fields=Country
|format=dynamic table
|details fields=Country
}}</div>

<table class="cargoDynamicTable display" data-details-fields="1" data-order="[]"><tr data-details="&lt;img src=x onerror=alert(2)&gt;"><td class="details-control">Click me</td></tr></table>

In the example, I'm using the Authors table from https://www.mediawiki.org/wiki/Extension:Cargo/Quick_start_guide, but this can be reproduced using any table.

  1. Click on the row with the "Click me" text

image.png (1,284×569 px, 37 KB)

Cause

A non-reserved data attribute is used to store HTML:
https://github.com/wikimedia/mediawiki-extensions-Cargo/blob/e89d34eeb509874b1fc035d42fe9a5158aeedc58/libs/ext.cargo.datatables.js#L90

Another data attribute is used for HTML at https://github.com/wikimedia/mediawiki-extensions-Cargo/blob/e89d34eeb509874b1fc035d42fe9a5158aeedc58/libs/ext.cargo.datatables.js#L53, but I didn't immediately find a way to create a custom element inside a <tfoot> tag, at least using the dynamic table format in Cargo. It should still be fixed.

Additional information

MW: 1.46.0-alpha (0990aaf)
Cargo: 3.8.6 (dd8b1d5)

Details

Author Affiliation
Wikimedia Communities
Related Changes in Gerrit:

Event Timeline

SomeRandomDeveloper added a subscriber: gerritbot.

This patch uses reserved data attributes where possible. Some non-reserved data attributes seem to be used by DataTables though, so to make sure those cannot be abused either, Cargo will now only turn tables with the data-mw-cargo-dynamic-table attribute into data tables.

@SomeRandomDeveloper - what's the reason for adding the "mw-" to every attribute name? Is that a MediaWiki convention?

My understanding of the convention is that core should use mw- and extensions should use e.g. ext-cargo-.

Data attributes starting with data-mw are reserved for core and extensions (https://github.com/wikimedia/mediawiki/blob/62a1dc8bdfc87a5db01beda2382baf562f8984c0/includes/Parser/Sanitizer.php#L593). They cannot be used in wikitext. If you want to store trusted data (HTML, URLs etc) in data attributes and use them in JS code, you need to use data-mw-... attributes, as it's otherwise possible for users to replicate them via wikitext and insert unsafe data.

My understanding of the convention is that core should use mw- and extensions should use e.g. ext-cargo-.

data-ext-... is not reserved. I could update my patch to use data-mw-cargo-..., but I feel like that would make the attribute names unnecessarily long

Good point, I was thinking that this was just about class names, I'd forgotten that about data attributes. Personally I probably would add the -cargo-, but as you have it looks good! +1 from me. (Not that I've tested it.)

Okay, I didn't know about "data-mw" - good to know.

Change #1237979 had a related patch set uploaded (by Yaron Koren; author: Yaron Koren):

[mediawiki/extensions/Cargo@master] Replace "data-" attributes with "data-mw-" in "dynamic table" format

https://gerrit.wikimedia.org/r/1237979

Change #1237979 merged by jenkins-bot:

[mediawiki/extensions/Cargo@master] Replace "data-" attributes with "data-mw-" in "dynamic table" format

https://gerrit.wikimedia.org/r/1237979

ASanford-WMF renamed this task from Stored XSS through the dynamic table format in Cargo to CVE-2026-39837: Stored XSS through the dynamic table format in Cargo.Apr 7 2026, 8:06 PM
ASanford-WMF changed the visibility from "Custom Policy" to "Public (No Login Required)".Apr 7 2026, 8:18 PM