All vulnerabilities
GHSA-4fr3-ghqj-28wx

mediawiki/semantic-media-wiki: Reflected XSS in Special:SMWAdmin ID lookup via unescaped id parameter

mediawiki/semantic-media-wikiApplications & CMS
CVSS
6.1Medium
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)No scoreNo FIRST EPSS score in this snapshot yet
Fixed in7.3.1Fixed versionGitHub
Published28 Sep 2026Updated 28 Sep 2026GitHub

What fixes it

  • 7.3.1mediawiki/semantic-media-wiki, composerGitHubcomposer require "mediawiki/semantic-media-wiki:^7.3.1"

A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.

Description

Summary

The administrative ID lookup form on Special:SMWAdmin reflects the request-controlled id parameter into an HTML warning box without escaping. When the ID does not match any stored entity, the value is rendered through a message that uses Semantic MediaWiki's plain-text message mode (equivalent to MediaWiki's Message::text()), which substitutes parameters verbatim into HTML. An attacker who lures an authenticated administrator (a user holding the smw-admin right) into opening a crafted link achieves reflected cross-site scripting in the administrator's session, same-origin with the wiki. No CSRF token is required in the link because the handler validates the token against a value that the special page overwrites with the current user's own token before routing.

Root Cause

The empty-references branch of the ID lookup builds a warning box from a message whose single parameter is the raw, request-derived id string. The message is emitted with the default plain-text type, which performs no HTML escaping of parameters, and the resulting string is then passed to a raw-HTML sink. The sibling branch in the same method deliberately uses the parse message type, and other nearby form fields use the escaped type, so the security invariant (escape untrusted data before raw-HTML emission) is understood elsewhere in the file but is missing on this one branch.

Affected component: Semantic MediaWiki Special:SMWAdmin ID lookup task handler
Vulnerable method: SMW\MediaWiki\Specials\Admin\Supplement\EntityLookupTaskHandler::createMessageFromRows
Sink location: src/MediaWiki/Specials/Admin/Supplement/EntityLookupTaskHandler.php:283-285
Message default type: src/Localizer/MessageLocalizerTrait.php:35-42 (defaults to plain-text mode)
Plain-text handler: src/Setup.php:276-286 (wfMessage(...)->text(), no escaping)
Auto-satisfied token: src/MediaWiki/Specials/SpecialAdmin.php:80-84

Impact

An attacker with no account and no privileges crafts a single GET URL. When an administrator holding the smw-admin right opens it, attacker-controlled markup executes as script in the administrator's browser in the wiki's origin. From that context the script can read and act with the administrator's session (for example issue authenticated requests, exfiltrate the session-scoped CSRF token, or perform privileged wiki actions the administrator is authorized for). The privileged-victim requirement narrows who can be targeted but does not reduce attacker control over the payload. Impact beyond in-session actions (such as full account takeover) is a plausible consequence of executing script in a privileged session and is not claimed here as demonstrated.

Proof of Concept

Preconditions: a wiki with Semantic MediaWiki installed (Special:SMWAdmin enabled by
default). The victim is a logged-in user holding the smw-admin right. No CSRF token or
prior state is required in the link.
  1. Construct the following URL against the target wiki:
https://VICTIM-WIKI/index.php/Special:SMWAdmin/lookup?id=%3Cimg%20src%3Dx%20onerror%3Dalert(document.domain)%3E
  1. Deliver it to a logged-in smw-admin administrator and have them open it.
  1. The ID matches no stored entity, so the empty-references branch renders the warning box. The response body contains the payload unescaped:
<div class="...warningbox...">The search was unable to match "<img src=x onerror=alert(document.domain)>" to a table entry.</div>

The <img> element is parsed as live markup and its onerror handler executes, demonstrating script execution in the administrator's origin.

Attack Chain

  1. Exposure: Special:SMWAdmin ships in the default admin task set and its /lookup subpage is enabled by default; execute() throws a permissions error for non-administrators, so the rendered page (and payload) is reached only in the context of an smw-admin victim, matching the reflected-XSS threat model.
  2. Control: The attacker fully controls the id request value. WebRequest::getText('id') only normalizes line endings and trims; it does not strip angle brackets, so < and > survive.
  3. Path: The /lookup subpage sets the action to lookup, routing to the ID lookup handler. A non-numeric payload avoids the numeric fast path and flows through the sortkey branch; addQuotes and a str_replace that only rewrites _ and * neutralize SQL but leave HTML metacharacters intact. No entity matches, so the empty-references else branch is reached deterministically.
  4. Guard: The only request-time guard is the edit-token check, which is auto-satisfied: the special page overwrites wpEditToken on the request object with the current user's own token before routing, so a link with no token passes. The vulnerable branch emits the message with the default plain-text type, which does not escape parameters, and the sink emits the content as raw HTML.
  5. Primitive: Attacker-controlled markup is written verbatim into a raw-HTML warning box that is added to the page output.
  6. Result: Reflected cross-site scripting executing in the authenticated administrator's browser session, same-origin with the wiki.

Bypass Evidence

No prior fix exists for this sink: the published Semantic MediaWiki cross-site scripting advisories (including CVE-2026-77606 for Special:Ask plain table headers, and advisories for Special:Ask sep and cursor token, Special:SearchByProperty, Special:URIResolver, the query debug formatter, Special:FacetedSearch, Special:Search extended profiles, and multiple Special:Browse stored issues) all target other endpoints. None references Special:SMWAdmin, the ID lookup form, or the entity-lookup task handler, so there is no existing remediation to bypass and no closed report to reconsider. This is an independently remediable path in the same weakness family as CVE-2026-77606.

Disproof attempts, all refuted against source and released tags 7.3.0 and 7.2.1: (1) The edit-token check does not block a bare GET link, because SpecialAdmin::execute sets wpEditToken to the current user's own token on the request object before the handler validates it (SpecialAdmin.php:80-84), verified byte-identical at 7.2.1. (2) WebRequest::getText does not sanitize HTML (line-ending normalization and trim only). (3) The SQL sortkey transforms (addQuotes and str_replace(['_','*'],[' ','%'])) affect only SQL quoting and the _/* characters; angle brackets pass through. (4) The reflected id is still the raw payload at the sink; the by-reference reset to an empty string occurs after the warning box is built. (5) The safe sibling branch uses the parse message type, but the attacker forces the empty-references else branch by supplying an ID that matches nothing. (6) The message default type is plain-text: no message localizer is set on the task handler, so the trait falls through to the plain-text handler wfMessage(...)->text(), which substitutes parameters raw. (7) All downstream sinks (the form paragraph renderer, the output formatter, and the core warning-box helper) emit content as raw HTML; only element attributes are escaped.

Affected Versions

  • Ecosystem: composer (Packagist)
  • Package: mediawiki/semantic-media-wiki
  • Confirmed affected range: <= 7.3.0
  • Latest release checked: 7.3.0 (Packagist)
  • Fix status: not fixed

The vulnerable sink and the auto-satisfied token behavior were verified byte-identical at released tags 7.3.0 (latest stable) and 7.2.1, and are also present on the unreleased development head. No fix exists on any branch. The introduced (lower) boundary is not established: released artifacts older than the inspected history could not be examined, so the range is left open at the low end rather than asserting an unverified introduction point. The upper bound <= 7.3.0 is verified against the latest released stable artifact.

Suggested Fix

Escape the untrusted id value before it reaches the raw-HTML warning box in the empty-references branch: emit the smw-admin-iddispose-no-references message with the escaped message type (mirroring the sibling branch that uses the parse type), or apply HTML escaping to the parameter before constructing the box. Audit the surrounding form-building code for any other message emitted with the default plain-text type that carries request-derived data into a raw-HTML sink. As an interim mitigation, operators can restrict the smw-admin right to a minimal set of trusted administrators and caution them against following untrusted Special:SMWAdmin links, though this does not remove the underlying flaw.

---

Reported by zx (GitHub: @manus-pi).

Text from GitHub Advisory Database

Affected versions 1

  • mediawiki/semantic-media-wiki, composer>= 3.1.0, < 7.3.1GitHub