GHSA-4c2h-67qq-vm87: Citizen skin vulnerable to stored XSS through multiple system messages
6.5
Basic Information
Technical Details
| Package Name | Ecosystem | Vulnerable Versions | First Patched Version |
|---|---|---|---|
| starcitizentools/citizen-skin | composer | >= 2.4.2, < 3.3.1 | 3.3.1 |
Vulnerability Intelligence
Miggo AI
Root Cause Analysis
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:
- Command Palette Tips: System messages used as tips were fetched using
mw.message().plain()(returning raw text) and then rendered via Vue'sv-html, leading to XSS. The fix involves usingmw.message().parse()to get sanitized HTML. - Menu Headings: Mustache templates (specifically
Menu.mustache) rendered menu heading labels (system messages) using{{{.}}}(unescaped HTML). The fix changes this to{{.}}for default escaping. - User Registration Date: A PHP function (
CitizenComponentUserInfo::getUserRegistration) directly embedded date-related system messages into HTML strings usingsprintf. The fix employsHtml::element()for safe HTML construction. - Preferences Menu Headings: A JavaScript function (
addDefaultPortlet) usedinnerHTMLto set heading labels derived from system messages viatextContent. WhiletextContentis generally safer, the use ofinnerHTMLas a sink was risky. The fix enforces the use oftextContentfor assignment, ensuring plain text interpretation. - No Results Messages: Another Mustache template (
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).