When using the RelatedArticles extension, arbitrary HTML and JS can be inserted into the DOM.
TextExtracts as the description source
Reproduction steps
- Enable the RelatedArticles extension
- Add $wgRelatedArticlesDescriptionSource = 'textextracts'; to your LocalSettings.php
- Create a page called RelatedArticlesXSS and insert <img src="" onerror="alert(1)"> into it
- Create a page called RelatedArticlesXSS2 and insert {{#related:RelatedArticlesXSS}} into it
- Visit RelatedArticlesXSS2
Cause
- The extracts prop for the RelatedArticlesXSS page is queried via the API: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/RelatedPagesGateway.js#L72-L102
- The API result is returned by getForCurrentPage: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/RelatedPagesGateway.js#L155
- The pages object of the query result is passed to the render function: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/index.js#L75-L89
- The innerHtml of the RelatedArticles container is set to the result of the RelatedArticles function, while passing the result of getCards (which doesn't escape any of the query results, but just assigns them to an object): https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/index.js#L55-L60
- Finally, the description is inserted as raw HTML: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/RelatedArticles.js#L30
Wikibase as the description source
Reproduction steps
- Enable the RelatedArticles extension
- Add $wgRelatedArticlesDescriptionSource = 'wikidata'; to your LocalSettings.php
- Have an item with a description like <img src="" onerror="alert(1)"> (note: <script>alert(1)</script> won’t do, the script gets injected into the DOM but not executed)
- Connect a wiki page to it via sitelink
- Declare that wiki page as a related article
Cause
- The description prop for the page is queried via the API: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/RelatedPagesGateway.js#L72-L102
- The API result is returned by getForCurrentPage: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/RelatedPagesGateway.js#L155
- The pages object of the query result is passed to the render function: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/index.js#L75-L89
- The innerHtml of the RelatedArticles container is set to the result of the RelatedArticles function, while passing the result of getCards (which doesn't escape any of the query results, but just assigns them to an object): https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/index.js#L55-L60
- Finally, the description is inserted as raw HTML: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/RelatedArticles.js#L30
Description2 as the description source
Reproduction steps
- Enable the Description2 extension
- Add $wgEnableMetaDescriptionFunctions = true; to your LocalSettings.php
- Enable the RelatedArticles extension
- Add $wgRelatedArticlesDescriptionSource = 'pagedescription'; to your LocalSettings.php
- Create a page called RelatedArticlesXSS and insert {{#description2:<img src="" onerror="alert(1)">}} into it
- Create a page called RelatedArticlesXSS2 and insert {{#related:RelatedArticlesXSS}} into it
- Visit RelatedArticlesXSS2
Cause
- The description page prop for the RelatedArticlesXSS page is queried via the API: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/RelatedPagesGateway.js#L72-L102
- The API result is returned by getForCurrentPage: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/RelatedPagesGateway.js#L155
- The pages object of the query result is passed to the render function: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/index.js#L75-L89
- The innerHtml of the RelatedArticles container is set to the result of the RelatedArticles function, while passing the result of getCards (which doesn't escape any of the query results, but just assigns them to an object): https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/index.js#L55-L60
- Finally, the description is inserted as raw HTML: https://github.com/wikimedia/mediawiki-extensions-RelatedArticles/blob/169e76305cbc9dc6a66f43c4116afaa42e39dcd7/resources/ext.relatedArticles.readMore/RelatedArticles.js#L30
Additional information
MediaWiki: 1.45.0-alpha (b6993c3)
PHP: 8.3.14 (fpm-fcgi)
RelatedArticles: 3.1.0 (169e763)
TextExtracts: 4ba1f5c
Description2: 0.4.1 (cdc06f2)
Browser: Firefox 139.0 on Fedora Linux 42



