Minimal test example: Special:PageStatistics?page=<script>alert('XSS')</script>
Expected results: no alert() is shown
Actual results: the alert() is, in fact, shown
Mitigation: wrapping the $requestedPage variable in htmlspecialchars( ..., ENT_QUOTES ) before outputting it, like so:
@@ -54,7 +59,8 @@ class SpecialPageStatistics extends SpecialPage { $this->renderPageStats(); } elseif ( $requestedPage ) { // @todo FIXME: internationalize - $out->addHTML( "<p>\"$requestedPage\" is either not a page or is not watchable</p>" ); + $safeRequestedPage = htmlspecialchars( $requestedPage, ENT_QUOTES ); + $out->addHTML( "<p>\"$safeRequestedPage\" is either not a page or is not watchable</p>" ); } else { $out->addHTML( "<p>No page requested</p>" ); }
(Excuse the line numbers presumably not matching as I have a lot of changes to this extension locally which I've yet to commit.)
Additionally there are various i18n issues here (and also many other places) and an alternative, even better fix would be to move the i18n string(s) into the i18n file and use $out->addWikiMsg( 'some-message-key-you-would-create', $requestedPage ); instead of $out->addHTML( ... ); to output a definitely known to be safe string without having to manually rely on htmlspecialchars() and the like and having the Parser do the sanitization etc. for you.
But I think the i18n stuff is a separate issue that can and should be fixed separately from the security issue.