Page MenuHomePhabricator

T407157-gerrit-REL1_43.patch

Authored By
SomeRandomDeveloper
Dec 8 2025, 11:57 PM
Size
8 KB
Referenced Files
None
Subscribers
None

T407157-gerrit-REL1_43.patch

From f53c841d4ba1ca7a49e37bf1a6af4bd36055a72f Mon Sep 17 00:00:00 2001
From: SomeRandomDeveloper <thisisnotmyname275@gmail.com>
Date: Tue, 4 Nov 2025 18:39:38 +0100
Subject: [PATCH] SECURITY: Fix several stored i18n XSS vulnerabilities
* Escape error messages passed to mw.errorDialog and
setStatus by default, except if they're objects.
* Use parseDom instead of .text() where necessary to
make sure custom formatting in the affected messages
doesn't break.
* Escape 'mwe-upwiz-other-v2' message when passing it to
.append()
Bug: T407157
Change-Id: I16de2211594ea9a686868ad7789f9879bf981fa1
---
i18n/en.json | 2 +-
resources/details/uw.TitleDetailsWidget.js | 8 +++++++-
resources/mw.FlickrChecker.js | 14 +++++++-------
resources/mw.UploadWizardDetails.js | 12 +++++++++---
resources/mw.errorDialog.js | 2 +-
resources/ui/steps/uw.ui.Upload.js | 2 +-
6 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/i18n/en.json b/i18n/en.json
index f8a89dd9..4f26de80 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -208,7 +208,7 @@
"mwe-upwiz-fileexists-replace-no-link": "Please choose a different title, because this title is already in use by another file.",
"mwe-upwiz-blacklisted-details-titleblacklist-custom-filename": "Please write a more informative title ([$2 view examples]).",
"mwe-upwiz-blacklisted-details-titleblacklist-custom-filename-title": "Title examples",
- "mwe-upwiz-blacklisted-details-titleblacklist-custom-filename-text": "<p><b>Examples of good file names:</b></p><ul><li>Nodnol skyline from Nodnol City Hall - Aug 2022</li><li>1875 Meeting of Settlers at Falconer Bay, New Nodland</li><li>Pseudohedron with no vertex visible from center</li></ul><br><p><b>Examples of bad file names:</b></p><ul><li>Image01</li><li>Joe</li><li>DSC00001</li><li>Foo.svg.png</li><li>30996951316264l</li><li>PSEUDOHEDRON WITH NO VERTEX VISIBLE FROM CENTER</li></ul><p><a href='https://commons.wikimedia.org/wiki/MediaWiki:Titleblacklist-custom-filename' target='_blank'>Learn more</a></p>",
+ "mwe-upwiz-blacklisted-details-titleblacklist-custom-filename-text": "<p><b>Examples of good file names:</b></p><ul><li>Nodnol skyline from Nodnol City Hall - Aug 2022</li><li>1875 Meeting of Settlers at Falconer Bay, New Nodland</li><li>Pseudohedron with no vertex visible from center</li></ul><br><p><b>Examples of bad file names:</b></p><ul><li>Image01</li><li>Joe</li><li>DSC00001</li><li>Foo.svg.png</li><li>30996951316264l</li><li>PSEUDOHEDRON WITH NO VERTEX VISIBLE FROM CENTER</li></ul><p>[https://commons.wikimedia.org/wiki/MediaWiki:Titleblacklist-custom-filename Learn more]</p>",
"mwe-upwiz-blacklisted-details": "This file name contains invalid characters or is in an invalid format. ([$2 Click here] for guidance on correcting this issue.)",
"mwe-upwiz-blacklisted-details-feedback": "Please write a different, descriptive title ([$2 more info]) • [$3 Send feedback]",
"mwe-upwiz-next": "Next",
diff --git a/resources/details/uw.TitleDetailsWidget.js b/resources/details/uw.TitleDetailsWidget.js
index e78f6fc5..62b30b11 100644
--- a/resources/details/uw.TitleDetailsWidget.js
+++ b/resources/details/uw.TitleDetailsWidget.js
@@ -209,7 +209,13 @@
var titleMessage = mw.message( messageKey + '-title' ),
title = titleMessage.exists() ? titleMessage.text() : '',
textMessage = mw.message( messageKey + '-text' ),
- text = textMessage.exists() ? textMessage.text() : result.blacklist.blacklistReason;
+ text = textMessage.exists() ? textMessage.parseDom() : result.blacklist.blacklistReason;
+
+ if ( typeof text === 'object' ) {
+ // T407157: Links created by jqueryMsg don't open in a new tab, but we don't want the user to
+ // lose their progress when clicking on a link. Therefore, we manually fix this here.
+ text.find( 'a' ).attr( 'target', '_blank' );
+ }
mw.errorDialog( text, title );
}
diff --git a/resources/mw.FlickrChecker.js b/resources/mw.FlickrChecker.js
index bcf171c0..899b0271 100644
--- a/resources/mw.FlickrChecker.js
+++ b/resources/mw.FlickrChecker.js
@@ -113,7 +113,7 @@ mw.FlickrChecker.prototype = {
}
} else {
// XXX show user the message that the URL entered was not valid
- mw.errorDialog( mw.message( 'mwe-upwiz-url-invalid', 'Flickr' ).escaped() );
+ mw.errorDialog( mw.msg( 'mwe-upwiz-url-invalid', 'Flickr' ) );
this.$spinner.remove();
this.ui.flickrInterfaceReset();
}
@@ -363,7 +363,7 @@ mw.FlickrChecker.prototype = {
photoset = data.photos;
}
if ( !photoset ) {
- $.Deferred().reject( mw.message( 'mwe-upwiz-url-invalid', 'Flickr' ).escaped() );
+ $.Deferred().reject( mw.msg( 'mwe-upwiz-url-invalid', 'Flickr' ) );
}
return photoset;
} );
@@ -482,7 +482,7 @@ mw.FlickrChecker.prototype = {
} );
if ( checker.imageUploads.length === 0 ) {
- return $.Deferred().reject( mw.message( 'mwe-upwiz-license-photoset-invalid' ).escaped() );
+ return $.Deferred().reject( mw.msg( 'mwe-upwiz-license-photoset-invalid' ) );
} else {
// eslint-disable-next-line no-jquery/no-global-selector
$( '#mwe-upwiz-flickr-select-list-container' ).show();
@@ -520,14 +520,14 @@ mw.FlickrChecker.prototype = {
photo_id: photoId
} ).then( ( data ) => {
if ( !data.photo ) {
- return $.Deferred().reject( mw.message( 'mwe-upwiz-url-invalid', 'Flickr' ).escaped() );
+ return $.Deferred().reject( mw.msg( 'mwe-upwiz-url-invalid', 'Flickr' ) );
}
return data.photo;
} ).then( ( photo ) => {
var isBlacklistedPromise = checker.isBlacklisted( photo.owner.nsid, photo.owner.path_alias );
return isBlacklistedPromise.then( ( isBlacklisted ) => {
if ( isBlacklisted ) {
- return $.Deferred().reject( mw.message( 'mwe-upwiz-user-blacklisted', 'Flickr' ).escaped() );
+ return $.Deferred().reject( mw.msg( 'mwe-upwiz-user-blacklisted', 'Flickr' ) );
} else {
return photo;
}
@@ -735,7 +735,7 @@ mw.FlickrChecker.prototype = {
}
upload.url = largestSize.source;
} else {
- mw.errorDialog( mw.message( 'mwe-upwiz-error-no-image-retrieved', 'Flickr' ).escaped() );
+ mw.errorDialog( mw.msg( 'mwe-upwiz-error-no-image-retrieved', 'Flickr' ) );
checker.$spinner.remove();
checker.ui.flickrInterfaceReset();
return $.Deferred().reject();
@@ -752,7 +752,7 @@ mw.FlickrChecker.prototype = {
// Set the license message to show the user.
var licenseMessage;
if ( licenseValue === 'invalid' ) {
- licenseMessage = mw.msg( 'mwe-upwiz-license-external-invalid', 'Flickr', licenseName );
+ licenseMessage = mw.message( 'mwe-upwiz-license-external-invalid', 'Flickr', licenseName ).parseDom();
} else {
licenseMessage = mw.msg( 'mwe-upwiz-license-external', 'Flickr', licenseName );
}
diff --git a/resources/mw.UploadWizardDetails.js b/resources/mw.UploadWizardDetails.js
index 0a403067..72265e55 100644
--- a/resources/mw.UploadWizardDetails.js
+++ b/resources/mw.UploadWizardDetails.js
@@ -248,7 +248,7 @@
new OO.ui.IconWidget( { icon: 'expand' } ).$element,
new OO.ui.IconWidget( { icon: 'collapse' } ).$element,
' ',
- mw.message( 'mwe-upwiz-other-v2', mw.user ).text()
+ mw.message( 'mwe-upwiz-other-v2', mw.user ).escaped()
),
classes: [
'mwe-upwiz-fieldLayout-additional-info',
@@ -1522,7 +1522,7 @@
*/
showError: function ( code, html ) {
this.showIndicator( 'error' );
- this.setStatus( html );
+ this.setStatus( Object.assign( html ) );
},
/**
@@ -1578,7 +1578,13 @@
},
setStatus: function ( s ) {
- this.$div.find( '.mwe-upwiz-file-status-line' ).html( s ).show();
+ const $statusLine = this.$div.find( '.mwe-upwiz-file-status-line' );
+ if ( typeof s === 'object' ) {
+ $statusLine.html( s );
+ } else {
+ $statusLine.text( s );
+ }
+ $statusLine.show();
},
// TODO: De-duplicate with code form mw.UploadWizardUploadInterface.js
diff --git a/resources/mw.errorDialog.js b/resources/mw.errorDialog.js
index eacb81eb..ee34f0df 100644
--- a/resources/mw.errorDialog.js
+++ b/resources/mw.errorDialog.js
@@ -12,7 +12,7 @@
*/
mw.errorDialog = function ( errorMessage, title ) {
OO.ui.getWindowManager().openWindow( 'upwizErrorDialog', {
- message: new OO.ui.HtmlSnippet( errorMessage ),
+ message: typeof errorMessage === 'object' ? new OO.ui.HtmlSnippet( errorMessage ) : errorMessage,
title: title || mw.message( 'mwe-upwiz-errordialog-title' ).text(),
verbose: true,
actions: [
diff --git a/resources/ui/steps/uw.ui.Upload.js b/resources/ui/steps/uw.ui.Upload.js
index c71d8e89..bdc8401d 100644
--- a/resources/ui/steps/uw.ui.Upload.js
+++ b/resources/ui/steps/uw.ui.Upload.js
@@ -480,7 +480,7 @@
* @param {string} filename
*/
uw.ui.Upload.prototype.showUnparseableFilenameError = function ( filename ) {
- this.showFilenameError( mw.message( 'mwe-upwiz-unparseable-filename', filename ).escaped() );
+ this.showFilenameError( mw.msg( 'mwe-upwiz-unparseable-filename', filename ) );
};
/**
--
2.52.0

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
22687879
Default Alt Text
T407157-gerrit-REL1_43.patch (8 KB)

Event Timeline