From d2e947a5f1b486aaf28a8863189d7fb494417d40 Mon Sep 17 00:00:00 2001
From: Brian Wolff <bawolff+wn@gmail.com>
Date: Wed, 18 Oct 2017 05:28:43 +0000
Subject: [PATCH] SECURITY: Escape internal error message

This message contains the request url, which is semi-user controlled.
Most browsers percent escape < and > so its probably not exploitable
(curl is an exception here), but nonetheless its not good.

Bug: T178451
Change-Id: I19358471ddf1b28377aad8e0fb54797c817bb6f6
---
 RELEASE-NOTES-1.29                         |  9 ++++++++-
 includes/exception/MWException.php         | 16 +++++++++-------
 includes/exception/MWExceptionRenderer.php | 16 +++++++++-------
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/RELEASE-NOTES-1.29 b/RELEASE-NOTES-1.29
index fb94166a52..ddab74b8e5 100644
--- a/RELEASE-NOTES-1.29
+++ b/RELEASE-NOTES-1.29
@@ -1,4 +1,11 @@
-== MediaWiki 1.29 ==
+== MediaWiki 1.29.1 ==
+This is a security and maintenance release of the MediaWiki 1.29 branch.
+
+=== Changes since 1.29.0 ===
+* (T178451) Potential XSS when $wgShowExceptionDetails = false and browser
+  sends non-standard url escaping.
+
+== MediaWiki 1.29.0 ==
 
 === Configuration changes in 1.29 ===
 * Default cookie expiration time has been reduced to 30 days. Login cookie
diff --git a/includes/exception/MWException.php b/includes/exception/MWException.php
index 4ff8636e2e..ac601bba07 100644
--- a/includes/exception/MWException.php
+++ b/includes/exception/MWException.php
@@ -114,13 +114,15 @@ class MWException extends Exception {
 			$logId = WebRequest::getRequestId();
 			$type = static::class;
 			return "<div class=\"errorbox\">" .
-			'[' . $logId . '] ' .
-			gmdate( 'Y-m-d H:i:s' ) . ": " .
-			$this->msg( "internalerror-fatal-exception",
-				"Fatal exception of type $1",
-				$type,
-				$logId,
-				MWExceptionHandler::getURL( $this )
+			htmlspecialchars(
+				'[' . $logId . '] ' .
+				gmdate( 'Y-m-d H:i:s' ) . ": " .
+				$this->msg( "internalerror-fatal-exception",
+					"Fatal exception of type $1",
+					$type,
+					$logId,
+					MWExceptionHandler::getURL( $this )
+				)
 			) . "</div>\n" .
 			"<!-- Set \$wgShowExceptionDetails = true; " .
 			"at the bottom of LocalSettings.php to show detailed " .
diff --git a/includes/exception/MWExceptionRenderer.php b/includes/exception/MWExceptionRenderer.php
index 46df663941..d4cc1523e8 100644
--- a/includes/exception/MWExceptionRenderer.php
+++ b/includes/exception/MWExceptionRenderer.php
@@ -225,13 +225,15 @@ class MWExceptionRenderer {
 		} else {
 			$logId = WebRequest::getRequestId();
 			$html = "<div class=\"errorbox mw-content-ltr\">" .
-				'[' . $logId . '] ' .
-				gmdate( 'Y-m-d H:i:s' ) . ": " .
-				self::msg( "internalerror-fatal-exception",
-					"Fatal exception of type $1",
-					get_class( $e ),
-					$logId,
-					MWExceptionHandler::getURL()
+				htmlspecialchars(
+					'[' . $logId . '] ' .
+					gmdate( 'Y-m-d H:i:s' ) . ": " .
+					self::msg( "internalerror-fatal-exception",
+						"Fatal exception of type $1",
+						get_class( $e ),
+						$logId,
+						MWExceptionHandler::getURL()
+					)
 				) . "</div>\n" .
 				"<!-- " . wordwrap( self::getShowBacktraceError( $e ), 50 ) . " -->";
 		}
-- 
2.14.1

