Page MenuHomePhabricator

Use img elements for x-xss language code
Closed, ResolvedPublicSecurity

Description

In T340201: Use custom language code to find i18n XSS issues, the x-xss language code was added to MediaWiki.
While this catches a lot of i18n XSSs caused by PHP code, vulnerabilities in Vue and JS code are often not caught by this, because script tags are not executed by the browser if inserted in certain ways.

Using an image tag with the src attribute set to an empty string and the onerror attribute set to JS code, more XSSs can be found.
This is why I locally use code similar to this to add an x-img-xss language code (taken from the x-xss task and modified):

$wgHooks['MessagesPreLoad'][] = function( $title, &$message, $code ) {
	if ( $code !== 'x-img-xss' ) {
		return true;
	}

	$key = lcfirst( preg_replace( '|/x-img-xss$|', '', $title ) );
	$rawMessages = \MediaWiki\MediaWikiServices::getInstance()
		->getMainConfig()
		->get( \MediaWiki\MainConfigNames::RawHtmlMessages );
	if ( in_array( $key, $rawMessages, true ) ) {
		return true;
	}

	$xssViaInnerHtml = "<img src=\"\" onerror=\"alert('$key')\">";
	$xssViaAttribute = '">' . $xssViaInnerHtml . '<x y="';
	$message = $xssViaInnerHtml . $xssViaAttribute;
	return false;
};

The following security tasks/advisories contain vulnerabilities that could have been found using this language code:

Therefore, it would be useful for the x-xss language code to use <img> elements instead, so developers are able to detect a wider range of vulnerabilities in their code.

Since there are likely many more of those vulnerabilities in production code, this task should stay private for now, similarly to T340201, but it would be good to have this feature built into MW core eventually.

Details

Risk Rating
Low
Author Affiliation
Wikimedia Communities
Related Changes in Gerrit:

Event Timeline

I think that is a good idea. innerHtml injection is quite common in js. I'd lean towards repurposing the existing code since onerror= should cover all the same cases plus more.

We might also want to consider a payload in cases where you can only inject into attributes, something like " autofocus tabindex=1 onfocus="alert(1)" as historically there have been some cases of that.

+1 for repurposing the existing language code rather than requiring testers to remember and try out twice as many language codes.

We might also want to consider a payload in cases where you can only inject into attributes, something like " autofocus tabindex=1 onfocus="alert(1)" as historically there have been some cases of that.

FWIW the current code tries to cover this by breaking out of the attribute and tag:

MessageCache::getMessageForLang()
$xssViaInnerHtml = "<script>alert('$lckey')</script>";
$xssViaAttribute = '">' . $xssViaInnerHtml . '<x y="';
return $xssViaInnerHtml . $xssViaAttribute . '($*)';
sbassett added a project: SecTeam-Processed.
sbassett added subscribers: gerritbot, sbassett.

Happy to review anything for this that lands in gerrit.

SomeRandomDeveloper renamed this task from Add x-img-xss language code to Use img elements for x-xss language code.Jul 28 2025, 9:25 PM
SomeRandomDeveloper updated the task description. (Show Details)
SomeRandomDeveloper changed the task status from Open to Stalled.Jul 28 2025, 9:27 PM

This is stalled at least until the next security release, since there are still vulnerabilities in Vector and other skins/extensions that could be easily found this way.

We can keep this bug private, but I don't really think it needs to be. We (read: Lucas) worked on the first x-xss language code functionality in public and we've found plenty of issues with that so far.

We can keep this bug private, but I don't really think it needs to be. We (read: Lucas) worked on the first x-xss language code functionality in public and we've found plenty of issues with that so far.

Using the new functionality causes multiple alerts when visiting any article using the Vector skin (T398636: CVE-2025-61657: Stored XSS through system messages in sticky header buttons in Vector). I think at least that one should be fixed and made public first.

I created {T403407} and https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1183701 as a public task without noticing that a private task existed for this.

It might be worth pushing the fix for T398636 to gerrit then after your patch was merged, since it would be a bit of an annoyance otherwise for anybody trying to use x-xss... Vector is bundled though, @sbassett what do you think?

We can keep this bug private, but I don't really think it needs to be. We (read: Lucas) worked on the first x-xss language code functionality in public and we've found plenty of issues with that so far.

IMHO that’s not true. I reported T340201 as a private task, and we only made it public after all the vulnerabilities found at the time had been fixed. (Sorry to be a month late on this, I don’t know why I didn’t notice it whenever I first read your comment.)

I created {T403407} and https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1183701 as a public task without noticing that a private task existed for this.

How did you manage that? The task description contains a link to this task with a summary of it, and I don’t see an “updated the task description” timeline item o_O

It might be worth pushing the fix for T398636 to gerrit then after your patch was merged, since it would be a bit of an annoyance otherwise for anybody trying to use x-xss... Vector is bundled though, @sbassett what do you think?

I suggest we should instead not yet merge the patch that will point any attentive developer to a Vector vulnerability that’s still unpatched in every third-party wiki. (It’s bad enough that it’s on Gerrit, but there’s no need to make things worse by merging it.)

I created {T403407} and https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1183701 as a public task without noticing that a private task existed for this.

How did you manage that? The task description contains a link to this task with a summary of it, and I don’t see an “updated the task description” timeline item o_O

Does it? I don't see T400585: Use img elements for x-xss language code mentioned at that task? The only reference to T400585 I can find at that task is Mentioned In T400585: Use img elements for x-xss language code which was caused by me linking that task here.

Ah, sorry, I didn’t pay attention to the link here:

As suggested in T340201#9210984

It might be worth pushing the fix for T398636 to gerrit then after your patch was merged, since it would be a bit of an annoyance otherwise for anybody trying to use x-xss... Vector is bundled though, @sbassett what do you think?

I suggest we should instead not yet merge the patch that will point any attentive developer to a Vector vulnerability that’s still unpatched in every third-party wiki. (It’s bad enough that it’s on Gerrit, but there’s no need to make things worse by merging it.)

Right, that would probably be a better idea. It should probably get merged with the next security release

Ah, sorry, I didn’t pay attention to the link here:

As suggested in T340201#9210984

To be clear, I definitely didn't see this task and was reviewing T340201: Use custom language code to find i18n XSS issues to see if the idea of using an img tag had been suggested (given I've found additional security issues through the img tag method). I did see that SomeRandomDeveloper had used the method to find i18n XSS, but was just inspired to take that further.

I found this task once I saw the Vector issue on my local and then saw it was linked from that task.

I suggest we make the other task private as well and somehow get that patch off gerrit, by overwriting or abandoning it

I suggest we make the other task private as well and somehow get that patch off gerrit, by overwriting or abandoning it

There isn't a good way to nuke patches of gerrit. The best that can be done is to upload a new version for the patch and then abandon, hoping that no one reviews the first version.

I suggest we make the other task private as well and somehow get that patch off gerrit, by overwriting or abandoning it

There isn't a good way to nuke patches of gerrit. The best that can be done is to upload a new version for the patch and then abandon, hoping that no one reviews the first version.

Yes, that's what I meant, and I've also seen somebody do this before for another security issue

I suggest we make the other task private as well and somehow get that patch off gerrit, by overwriting or abandoning it

There isn't a good way to nuke patches of gerrit. The best that can be done is to upload a new version for the patch and then abandon, hoping that no one reviews the first version.

Yes, that's what I meant, and I've also seen somebody do this before for another security issue

I've overridden it with a commit message that shouldn't attract attention and made the commit empty per the idea of the commit message

SomeRandomDeveloper changed the task status from Stalled to Open.Oct 3 2025, 9:45 PM

This is no longer blocked by Vector. It might be worth checking core and a few other WMF-deployed skins / bundled extensions for other obvious vulnerabilities that could be found through this, but I'd be fine with making this public and @Dreamy_Jazz uploading their patch again if nothing turns up.

Change #1183701 had a related patch set uploaded (by Dreamy Jazz; author: Dreamy Jazz):

[mediawiki/core@master] Update x-xss language to use img tag for the XSS payload

https://gerrit.wikimedia.org/r/1183701

This is no longer blocked by Vector. It might be worth checking core and a few other WMF-deployed skins / bundled extensions for other obvious vulnerabilities that could be found through this, but I'd be fine with making this public and @Dreamy_Jazz uploading their patch again if nothing turns up.

Thanks. I've restored the patch and it's ready for review

This is no longer blocked by Vector. It might be worth checking core and a few other WMF-deployed skins / bundled extensions for other obvious vulnerabilities that could be found through this, but I'd be fine with making this public and @Dreamy_Jazz uploading their patch again if nothing turns up.

Thanks. I've restored the patch and it's ready for review

Thanks! @sbassett I think this task can be made public then.

sbassett changed the visibility from "Custom Policy" to "Public (No Login Required)".
sbassett changed the edit policy from "Custom Policy" to "All Users".
sbassett changed Risk Rating from N/A to Low.

Change #1183701 merged by jenkins-bot:

[mediawiki/core@master] Update x-xss language to use img tag for the XSS payload

https://gerrit.wikimedia.org/r/1183701