The non-jqueryMsg version of `mw.message( … ).parse()` doesn't escape HTML. This affects both message contents (which are generally safe) and the parameters (which can be based on user input). (When jqueryMsg *is* loaded, it correctly accepts only whitelisted tags in message contents, and escapes all parameters.)
There are two cases when it's used:
* When the `mediawiki.jqueryMsg` ResourceLoader module is not loaded. This is unlikely to be an issue in practice because:
** Tons of things load jqueryMsg these days, it's probably included on almost all pages on any serious wiki. I managed to reproduce the issue on Special:SpecialPages on a wiki with no extensions installed.
** Calling .parse() only makes sense if you have loaded jqueryMsg, so unless other modules have missing dependencies, this never happens.
* When jqueryMsg thinks the message is "simple" and falls back to the basic version to avoid expensive parsing. This is done for messages that do not contain `{{`, `[`, `<`, `>`, `&`.
** Since that check ensures that these messages don't contain HTML themselves, this leaves the problem of unescaped parameters.
```
// This message contains '<', so it will always go through jqueryMsg if it's loaded
mw.messages.set( 'foo1', '<img onerror="alert()" src="foo">' );
$( 'body' ).append( mw.message( 'foo1' ).parse() );
// This message also contains '<', so it will always go through jqueryMsg if it's loaded
mw.messages.set( 'foo2', '<b>$1</b>' );
$( 'body' ).append( mw.message( 'foo2', '<img onerror="alert()" src="foo">' ).parse() );
// This message will never go through jqueryMsg
mw.messages.set( 'foo3', '$1' );
$( 'body' ).append( mw.message( 'foo3', '<img onerror="alert()" src="foo">' ).parse() );
```
The non-jqueryMsg implementation of .parse() should probably escape the output. Basically, it should be equivalent to .escaped() and not .text(). (Take care not to accidentally double-escape in the jqueryMsg case.)