From 27a96656537f3f8189f395018e7f03546f64bebb Mon Sep 17 00:00:00 2001
From: Lucas Werkmeister <lucas.werkmeister@wikimedia.de>
Date: Tue, 10 Jun 2025 16:11:24 +0200
Subject: [PATCH] SECURITY: Escape card details

The title and description are probably the most important, but the rest
seems prudent to escape too.

mw.html is part of the mediawiki.base module, so no new ResourceLoader
dependency should be necessary.

Bug: T396413
Change-Id: SECURITY-I18f98a31ba40ff244c6944e2f9e1c4bee1319abf
---
 .../ext.relatedArticles.readMore/RelatedArticles.js  | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/resources/ext.relatedArticles.readMore/RelatedArticles.js b/resources/ext.relatedArticles.readMore/RelatedArticles.js
index 997fabd0fa..c1209f32d5 100644
--- a/resources/ext.relatedArticles.readMore/RelatedArticles.js
+++ b/resources/ext.relatedArticles.readMore/RelatedArticles.js
@@ -14,20 +14,20 @@ const RelatedArticles = ( options ) => [
 		`<div class="read-more-container ${ ( options.isContainerSmall ) ? 'read-more-container-small' : 'read-more-container-large' }">`,
 			`<aside class="noprint">`,
 				( options.heading ) ?
-				`<h2 class="read-more-container-heading">${ options.heading }</h2>` : ``,
+				`<h2 class="read-more-container-heading">${ mw.html.escape( options.heading ) }</h2>` : ``,
 				`<ul class="read-more-container-card-list">`,
-					options.cards.map( ( card ) => `<li title="${ card.label }">
-					<a href="${ card.url }" ${ options.clickEventName ? `data-event-name="${ options.clickEventName }"` : '' }><span class="cdx-card">
+					options.cards.map( ( card ) => `<li title="${ mw.html.escape( card.label ) }">
+					<a href="${ mw.html.escape( card.url ) }" ${ options.clickEventName ? `data-event-name="${ mw.html.escape( options.clickEventName ) }"` : '' }><span class="cdx-card">
 						<span class="cdx-card__thumbnail cdx-thumbnail">
 						${ ( card.thumbnail && card.thumbnail.url ) ?
-							`<span class="cdx-thumbnail__image" style="background-image: url('${ card.thumbnail.url }')"></span>` :
+							`<span class="cdx-thumbnail__image" style="background-image: url('${ mw.html.escape( card.thumbnail.url ) }')"></span>` :
 							`<span class="cdx-thumbnail__placeholder">
 								<span class="cdx-thumbnail__placeholder__icon"></span>
 							</span>` }
 						</span>
 						<span class="cdx-card__text">
-							<span class="cdx-card__text__title">${ card.label }</span>
-							<span class="cdx-card__text__description">${ card.description }</span>
+							<span class="cdx-card__text__title">${ mw.html.escape( card.label ) }</span>
+							<span class="cdx-card__text__description">${ mw.html.escape( card.description ) }</span>
 						</span>
 					</a>
 				</li>` ).join( '\n' ),
-- 
2.49.0

