Page MenuHomePhabricator

Arbitrary HTML injection through error display on Wikifunctions
Closed, ResolvedPublicSecurity

Description

  • Go to Z28154
  • Insert whatever value in the first function input parameter (for example "Z7"
  • In the second input parameter (labeled as "parameters") insert one element: <button onmouseover="window.location='//www.example.com'">
  • Execute the function
  • Click on "Details": the HTML code is injected directly in the error details window; the button is present, and the JS code associated with it can be executed by hovering the mouse over it.

This is important because it is very easy (no special user right required) to create a permanent testcase that injects HTML code every time someone tries to see the details.

Event Timeline

sbassett changed the task status from Open to In Progress.Sep 11 2025, 8:30 PM
sbassett raised the priority of this task from High to Unbreak Now!.
sbassett added a project: Vuln-XSS.
sbassett subscribed.

Confirmed the exploit works. Setting UBN since this is an XSS that could theoretically be executed cross-project.

Quick patch; think this gets all of it:

This will break the usability testing, but oh well.

Quick patch; think this gets all of it:

This will break the usability testing, but oh well.

CR+2, most of this make sense to me: mustache/vue-style escapes around the getErrorMessage( error ) calls and then a i18n parse call.

This fixed the bits I noticed with malicious error labels, but not the reported issue with malicious error arguments; I've now got an improved version:

OK, third time's the charm:

Screenshot 2025-09-11 at 19.22.03.png (2×2 px, 766 KB)

We'll have to consider in the morning if there are other abuse routes I've missed, and how we can fix the system to provide the functionality wanted without this issue, but for tonight I think we're done.

sbassett lowered the priority of this task from Unbreak Now! to High.
sbassett awarded a token.

OK, third time's the charm:

Thanks! I can confirm that the example payload within the task description can no longer be reproduced in production. Let's plan to follow up tomorrow.

@Jdforrester-WMF After this patch lands publicly in Gerrit, please consider replacing the <!-- eslint-disable vue/no-v-html --> comments that it does leave in / add in to use eslint-disable-next-line instead. Otherwise you could still be missing uses of v-html that occur anywhere in the same file below the first one.

For the record, @Dv103 has also disclosed some details about this task publicly (before it was even fixed – timestamps are in UTC+2):

image.png (304×488 px, 39 KB)

Given that, and the fact that there are probably very few other (non-dev) WikiLambda installs around, it’s probably best to publish the task+fix relatively soon? (I.e. without waiting for the next full security release, at least IMHO.)

Fixed another related error argument label vulnerability on top of James' latest version. I've checked injection on error string arguments, but also error labels and error argument labels. This should do it:

Screenshot from 2025-09-12 12-52-41.png (466×543 px, 56 KB)

Screenshot from 2025-09-12 13-05-24.png (519×735 px, 29 KB)

Screenshot from 2025-09-12 12-52-47.png (478×721 px, 27 KB)

@Jdforrester-WMF After this patch lands publicly in Gerrit, please consider replacing the <!-- eslint-disable vue/no-v-html --> comments that it does leave in / add in to use eslint-disable-next-line instead. Otherwise you could still be missing uses of v-html that occur anywhere in the same file below the first one.

Yeah, the multi-line Vue code breaks eslint-disable-next-line directives; will add the re-enables in.

For the record, @Dv103 has also disclosed some details about this task publicly (before it was even fixed – timestamps are in UTC+2):

image.png (304×488 px, 39 KB)

Eurgh, thanks for flagging. @Dv103, please don't discuss private tasks publicly.

Given that, and the fact that there are probably very few other (non-dev) WikiLambda installs around, it’s probably best to publish the task+fix relatively soon? (I.e. without waiting for the next full security release, at least IMHO.)

Yes, that's the plan.

Fixed another related error argument label vulnerability on top of James' latest version. I've checked injection on error string arguments, but also error labels and error argument labels. This should do it:

Thanks! Very slight tweak to add the eslint-disable fixes Roan suggested, and split into a second git commit on top of the deployed one, for easier management.

{F66017626}

Will deploy now.

OK, I believe we're now good to push the patches to gerrit and land into master. @sbassett, can you confirm that's OK?

OK, I believe we're now good to push the patches to gerrit and land into master. @sbassett, can you confirm that's OK?

LGTM, thanks! I've verified the patches appear correct on deployment:

$ ls /srv/patches/1.45.0-wmf.18/extensions/WikiLambda/
01-T404392.patch  02-T404392.patch
...
$ pwd
/srv/mediawiki-staging/php-1.45.0-wmf.18/extensions/WikiLambda
...
$  git log --graph --decorate --oneline -n2
* 7753571d (HEAD) SECURITY: Do not let error type labels or arguments return HTML either
* 6b5ca6bc SECURITY: Do not let getErrorMessages() etc. return HTML ever, at least for now

And we're also now tracking the patches under T276237 and T397776.

SecurityPatchBot changed the task status from In Progress to Open.Sep 12 2025, 11:54 PM
SecurityPatchBot raised the priority of this task from High to Unbreak Now!.
Patch is blocking upcoming release

Patch 01-T404392.patch is currently failing to apply for the most recent code in the mainline branch of extensions/WikiLambda. This is blocking MediaWiki release 1.45.0-wmf.19(T396380)


If the patch needs to be rebased

A new version of the patch can be placed at the right location in the deployment server with the following Scap command:

REVISED_PATCH=<path_to_revised_patch>
scap update-patch --message-body 'Rebase to solve merge conflicts' /srv/patches/next/extensions/WikiLambda/01-T404392.patch "$REVISED_PATCH"

If the patch has been made public

The patch can be dropped in the deployment server with the following Scap command:

scap remove-patch --message-body 'Dropping patch already made public' /srv/patches/next/extensions/WikiLambda/01-T404392.patch
sbassett changed the task status from Open to In Progress.Sep 13 2025, 1:08 AM
sbassett lowered the priority of this task from Unbreak Now! to High.

We'll want to fix any merge conflicts for 01-T404392.patch prior to 1.45.0-wmf.19 rollout next week.

SecurityPatchBot changed the task status from In Progress to Open.Sep 13 2025, 11:53 PM
SecurityPatchBot raised the priority of this task from High to Unbreak Now!.
Patch is blocking upcoming release

Patch 01-T404392.patch is currently failing to apply for the most recent code in the mainline branch of extensions/WikiLambda. This is blocking MediaWiki release 1.45.0-wmf.19(T396380)


If the patch needs to be rebased

A new version of the patch can be placed at the right location in the deployment server with the following Scap command:

REVISED_PATCH=<path_to_revised_patch>
scap update-patch --message-body 'Rebase to solve merge conflicts' /srv/patches/next/extensions/WikiLambda/01-T404392.patch "$REVISED_PATCH"

If the patch has been made public

The patch can be dropped in the deployment server with the following Scap command:

scap remove-patch --message-body 'Dropping patch already made public' /srv/patches/next/extensions/WikiLambda/01-T404392.patch
sbassett lowered the priority of this task from Unbreak Now! to High.Sep 14 2025, 11:51 PM
SecurityPatchBot raised the priority of this task from High to Unbreak Now!.Sep 14 2025, 11:54 PM
Patch is blocking upcoming release

Patch 01-T404392.patch is currently failing to apply for the most recent code in the mainline branch of extensions/WikiLambda. This is blocking MediaWiki release 1.45.0-wmf.19(T396380)


If the patch needs to be rebased

A new version of the patch can be placed at the right location in the deployment server with the following Scap command:

REVISED_PATCH=<path_to_revised_patch>
scap update-patch --message-body 'Rebase to solve merge conflicts' /srv/patches/next/extensions/WikiLambda/01-T404392.patch "$REVISED_PATCH"

If the patch has been made public

The patch can be dropped in the deployment server with the following Scap command:

scap remove-patch --message-body 'Dropping patch already made public' /srv/patches/next/extensions/WikiLambda/01-T404392.patch
sbassett lowered the priority of this task from Unbreak Now! to High.Sep 15 2025, 12:00 AM
jnuche raised the priority of this task from High to Unbreak Now!.EditedSep 15 2025, 8:27 AM
jnuche subscribed.

Noting here the 02-T404392 patch for 1.45.0-wmf.18 is unfortunately also failing.

This is blocking backport deployments at the moment: https://spiderpig.wikimedia.org/jobs/549

[FAILED] /srv/patches/1.45.0-wmf.18/extensions/WikiLambda/02-T404392.patch
sbassett lowered the priority of this task from High to Low.Sep 15 2025, 5:01 PM
sbassett changed the visibility from "Custom Policy" to "Public (No Login Required)".Oct 21 2025, 5:28 PM
sbassett changed the edit policy from "Custom Policy" to "All Users".
sbassett changed Risk Rating from N/A to Medium.
sbassett moved this task from Watching to Our Part Is Done on the Security-Team board.