The vulnerability GHSA-4c2h-67qq-vm87 in the Citizen skin for MediaWiki encompasses multiple stored Cross-Site Scripting (XSS) vulnerabilities. These vulnerabilities stem from the improper handling of system messages, which can be edited by users with editinterface permissions. These messages were inserted into various parts of the user interface without adequate sanitization or escaping, allowing malicious HTML to be rendered in the victim's browser.
The analysis of the provided commits, particularly the security patch 93c36ac778397e0e7c46cf7adb1e5d848265f1bd, reveals several key areas of weakness:
mw.message().plain() (returning raw text) and then rendered via Vue's v-html, leading to XSS. The fix involves using mw.message().parse() to get sanitized HTML.Menu.mustache) rendered menu heading labels (system messages) using {{{.}}} (unescaped HTML). The fix changes this to {{.}} for default escaping.CitizenComponentUserInfo::getUserRegistration) directly embedded date-related system messages into HTML strings using sprintf. The fix employs Html::element() for safe HTML construction.addDefaultPortlet) used innerHTML to set heading labels derived from system messages via textContent. While textContent is generally safer, the use of innerHTML as a sink was risky. The fix enforces the use of textContent for assignment, ensuring plain text interpretation.TypeaheadPlaceholder.mustache) rendered search-related system messages (title and description for no results) using {{{.}}}. The fix, again, is to use {{.}} for proper escaping.The root cause across these instances is the trust placed in the content of system messages when rendering them in an HTML context. Since these messages can be altered by privileged users, they must be treated as untrusted input and sanitized or escaped appropriately before being included in the DOM. The patches address this by either changing how the messages are fetched/parsed (to ensure they are safe HTML) or by changing how they are rendered (to ensure they are treated as plain text or safely escaped HTML).
uselang parameter set to x-xssOn the main page of my test wiki, the following messages were shown: navigation, notifications, user-interface-preferences, personaltools, variants, views, associated-pages, cactions and toolbox.
This impacts wikis where a group has the editinterface but not the editsitejs user right.
Various date messages returned by Language::userDate are inserted into raw HTML, allowing anybody who can edit those messages to insert arbitrary HTML into the DOM.
The result of $this->lang->userDate( $timestamp, $this->user ) returns unescaped values, but is inserted as raw HTML by Citizen:
https://github.com/StarCitizenTools/mediawiki-skins-Citizen/blob/072e4365e9084e4b153eac62d3666566c06f5a49/includes/Components/CitizenComponentUserInfo.php#L55-L60
november:
This impacts wikis where a group has the editinterface but not the editsitejs user right.
Various preferences messages are inserted into raw HTML, allowing anybody who can edit those messages to insert arbitrary HTML into the DOM.
The innerHtml of the label div is set to the textContent of the label, essentially unsanitizing the system messages:
https://github.com/StarCitizenTools/mediawiki-skins-Citizen/blob/407052e7069bdeae927d6f1a2a1c9a45b473bf9a/resources/skins.citizen.preferences/addPortlet.polyfill.js#L18
citizen-feature-custom-font-size-name (or any other message displayed in a heading in the preferences menu) to <img src="" onerror="alert('citizen-feature-custom-font-size-name')"> (script tags don't work here due to the way the HTML is inserted)The citizen-search-noresults-title and citizen-search-noresults-desc system messages are inserted into raw HTML, allowing anybody who can edit those messages to insert arbitrary HTML into the DOM.
The system messages are inserted as raw HTML by the mustache template: https://github.com/StarCitizenTools/mediawiki-skins-Citizen/blob/407052e7069bdeae927d6f1a2a1c9a45b473bf9a/resources/skins.citizen.search/templates/TypeaheadPlaceholder.mustache#L8-L9
citizen-search-noresults-title and citizen-search-noresults-desc to <img src="" onerror="alert('citizen-search-noresults-title')"> and <img src="" onerror="alert('citizen-search-noresults-desc')"> (script tags don't work here due to the way the HTML is inserted)
This impacts wikis where a group has the editinterface but not the editsitejs user right.
| Package Name | Ecosystem | Vulnerable Versions | First Patched Version |
|---|---|---|---|
| starcitizentools/citizen-skin | composer | >= 2.4.2, < 3.3.1 | 3.3.1 |
Ongoing coverage of React2Shell