GitHub Advisoryadvisory · Packagist

GHSA-9rcc-pmj8-ffhr Semantic MediaWiki's Special:FacetedSearch cstate hidden inputs enable reflected XSS (residual of CVE-2025-10354)

MEDIUM Published 2026-09-18 Modified 2026-09-18 Official page ↗
Ecosystem
Packagist
Packages
mediawiki/semantic-media-wiki
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Weaknesses
CWE-79
Reviewed
2026-09-18

Affected packages

• Packagist mediawiki/semantic-media-wiki: >= 4.2.0, < 7.2.1 → fixed in 7.2.1

Description

Summary Special:FacetedSearch `cstate` hidden inputs enable reflected XSS (residual of CVE-2025-10354) Details Affected versions and vulnerable location • Confirmed present on latest shipped release tag available in the local clone: `SemanticMediaWiki/[email protected]`. • Confirmed present on default branch `master` at HEAD `18f418b4cdf2875e67a741349179a22c1573f61c`. Vulnerable sink (default-branch representation): • `src/MediaWiki/Specials/FacetedSearch/HtmlBuilder.php:131-133` • Builds `$hidden` by concatenating unescaped request-controlled `cstate[$key]` values into an HTML attribute context (`value="..."`). • `templates/FacetedSearch/search.mustache:25` • Inserts the constructed fragment via `{{{hidden}}}` (no HTML escaping at this boundary). Reachability trace (verified from source) 1. HTTP entrypoint: • `GET` to `Special:FacetedSearch` dispatches into `SMW\MediaWiki\Specials\SpecialFacetedSearch::execute()`. 2. Request decoding boundary: • `SpecialFacetedSearch::execute()` constructs `UrlArgs` from `$request->getValues()` and calls `ParametersProcessor::checkRequest($request)`. 3. Checksum gate: • `ParametersProcessor::checkRequest()` clears `cstate` only when `filtered != 1` and `getInt('csum', 0) != crc32(getVal('q', ''))`. 4. Decoder -> HTML assembly: • `HtmlBuilder::buildHTML()` iterates `foreach ( $urlArgs->getArray( 'cstate' ) as $key => $value )` and concatenates each into `$hidden` without escaping. • `HtmlBuilder::buildHTML()` passes `$hidden` into the template variable `hidden`. 5. HTML injection sink: • `templates/FacetedSearch/search.mustache` renders `{{{hidden}}}` into the ``, so the concatenated markup is inserted as raw HTML. PoC Reproduction steps (source-derived) 1. Choose a `q` value. 2. Compute `csum` as `crc32(q)`. 3. Send a request that includes: • `q=` • `csum=` • at least one `cstate[]=` entry Example request shape: ```text /index.php/Special:FacetedSearch?q=Text&csum=&cstate[0]=x%22%20autofocus%20onfocus%3Dalert(1)%20x%22 ``` Impact Attacker model • Any remote attacker who can send HTTP requests to `Special:FacetedSearch` (or the localized alias mapped to the same `SpecialFacetedSearch` class) can supply attacker-controlled query parameters. • Preconditions: • The attacker must make `cstate` survive `ParametersProcessor::checkRequest()`, either by setting `csum` to `crc32(q)` (when `filtered != 1`), or by setting `filtered=1`. • The attacker must supply `cstate[]` values containing characters that break out of the HTML `value="..."` attribute context (for example an injected `"` to terminate the attribute value). Severity and CVSS reasoning Proposed severity: MEDIUM. Proposed CVSS v3.1 vector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N`. Rationale: • AV:N: delivered over the network via query parameters. • AC:L: requires only setting `q`, `csum`, and at least one `cstate` entry. • PR:N: no authentication required for the request path in this code. • UI:R: the victim must load the crafted URL. • S:C: reflected XSS executes in the wiki origin and can affect other users depending on deployment and browser behavior. Why this is a residual of CVE-2025-10354 • The CVE-2025-10354 hardening shipped by escaping the `q` parameter before emitting it into the `value="{{q}}"` attribute. • Commit `3d675ce` updates only the `q` rendering to use `htmlspecialchars( $urlArgs->get( 'q', '' ) )` and does not touch the adjacent `cstate` -> `$hidden` construction loop. • As a result, `cstate` remains an unescaped input source that flows into the same raw template injection point (`{{{hidden}}}`), creating a distinct reflected-XSS lane. Output (from code inspection) Given the payload idea where `cstate[0]` starts with `x" ... x"`, `HtmlBuilder.php` constructs the hidden fragment by concatenation: ```html ``` Because `search.mustache` injects the fragment via `{{{hidden}}}`, the attacker-controlled markup participates in normal HTML parsing in the response body. Suggested fix • Escape both the `cstate` key and value when constructing `$hidden`. • Minimal code change in `src/MediaWiki/Specials/FacetedSearch/HtmlBuilder.php`: ```php foreach ( $urlArgs->getArray( 'cstate' ) as $key => $value ) { $safeKey = htmlspecialchars( (string)$key, ENT_QUOTES, 'UTF-8' ); $safeValue = htmlspecialchars( (string)$value, ENT_QUOTES, 'UTF-8' ); $hidden .= ''; } ``` This keeps the raw `{{{hidden}}}` template insertion safe by ensuring the concatenated HTML fragment itself is attribute-escaped. How I found it and a note on tooling I anchored on the published CVE-2025-10354 patch by verifying in the checked-out repository that commit `3d675ce` changes only the `q` rendering in `HtmlBuilder.php` to use `htmlspecialchars`. Then I traced the reachable request path from `SpecialFacetedSearch::execute()` through `ParametersProcessor::checkRequest()` (checksum gate for whether `cstate` survives) into `HtmlBuilder::buildHTML()` where `$hidden` is constructed from `cstate` without escaping and injected into `templates/FacetedSearch/search.mustache` via `{{{hidden}}}`. (End of file) AI tooling I used AI assistance for the code audit and for drafting this report. I manually verified the finding against the project's source at the location cited above before reporting it, and the severity and impact assessment are my own.

Related

Weakness · CWE (1)

  • CWE-79 Improper Neutralization of Input During Web Page Generation weakness

References