Page MenuHomePhabricator

Use of preloadparams[] on action=edit with values matching the internal array structure of message parameters can result in injection (with display_errors=1) or fatal errors/type errors
Closed, ResolvedPublicSecurity

Description

It could be called a feature, but it can make problems and resulting in fatal or html injection:

Where it happens?
When starting to edit a new section on a wiki page or starting to create a new page, it is possible to use a preload= parameter in the url to fill in the text area with the content of that page. With the url parameter preloadparams it is possible to replace placeholder like $1 in that text. That is done using the Message::class. When providing an internal array structure of Message as parameter the replaced placeholder is formatted for that.

Example:
https://www.mediawiki.org/w/index.php?title=Special:MyPage&action=edit&section=new&preload=Manual%3ACreating_pages_with_preloaded_text%2Fparam_demo&preloadparams%5B0%5D%5Bdatetime%5D=1666216800&preloadparams%5B1%5D%5Bperiod%5D=1666216800&preloadparams%5B2%5D=valid

The text

*First parameter is $1
*Second parameter is $2
*Third parameter is $3

is processed to

*First parameter is 22:00, 19 October 2022
*Second parameter is 19,284 d 22 h 0 min 0 s
*Third parameter is valid

It is possible to use everything message supports, even lists formatted with pipes

https://www.mediawiki.org/w/index.php?title=Special:MyPage&action=edit&section=new&preload=Manual%3ACreating_pages_with_preloaded_text%2Fparam_demo&preloadparams%5Blist%5D%5B0%5D=item1&preloadparams%5Blist%5D%5B1%5D=item2&preloadparams%5Btype%5D=pipe

*First parameter is item1 | item2
*Second parameter is $2
*Third parameter is $3

The Problem
All the magic is done in Message::extractParam where the multi dim arrays from $_GET are given too. When looking there it also possible to produce type errors (Message::formatListParam needs an array as second argument) or fatals when $obj->__toString() is called with a string.

Examples to get type error:

To get exception

The security issue I found is when using the list with an invalid type, because Message::formatListParam calls a trigger_error with the unescaped message key. The message key in this case is the whole wikitext of the preloaded page. When the preloaded page contains some script-tags, the raw script tag is now part of the html when the php setting display_errors is on, which is not true for wmf wikis, but possible for third parties. Feel free to review this fact and possible make this public, if not an issue (Better safe than sorry from my point of view)

To see that:

  1. Create a Page "PreloadUnsafe" with content "Argument: $1 <script>alert('XSS');</script>"
  2. Put ini_set( 'display_errors', 1 ); into LocalSettings
  3. Open index.php?action=edit&section=new&preload=PreloadUnsafe&preloadparams%5Blist%5D%5B0%5D=item1&preloadparams%5Blist%5D%5B1%5D=item2&preloadparams%5Btype%5D=invalid and enjoy
  4. Getting as raw html:
<b>Warning</b>:  trigger: Invalid list type for message "Argument: $1
<script>alert('XSS');</script>": invalid (params are a:2:{i:0;s:5:&quot;item1&quot;;i:1;s:5:&quot;item2&quot;;}) in <b>includes\language\Message.php</b> on line <b>1529</b>

A solution would be to reject multi-dim arrays in WebRequest::getArray/getIntArray, that would fix all pages with possible problems using arrays, it should fix T321133 as well. I was reviewing the patch set there and found the issue reported here. But that would also break the "feature" of formatted arguments on preload, but that sounds acceptable.

Details

Risk Rating
Medium
Author Affiliation
Wikimedia Communities

Event Timeline

A solution would be to reject multi-dim arrays in WebRequest::getArray/getIntArray, that would fix all pages with possible problems using arrays, it should fix T321133 as well. I was reviewing the patch set there and found the issue reported here. But that would also break the "feature" of formatted arguments on preload, but that sounds acceptable.

I have proposed this previously in https://gerrit.wikimedia.org/r/c/mediawiki/core/+/665385 / T275238 as a security hardening measure (I didn't find the actual bug at the time), but the patch caused test failures, so I gave up on the attempt.

A solution would be to reject multi-dim arrays in WebRequest::getArray/getIntArray, that would fix all pages with possible problems using arrays, it should fix T321133 as well. I was reviewing the patch set there and found the issue reported here. But that would also break the "feature" of formatted arguments on preload, but that sounds acceptable.

I have proposed this previously in https://gerrit.wikimedia.org/r/c/mediawiki/core/+/665385 / T275238 as a security hardening measure (I didn't find the actual bug at the time), but the patch caused test failures, so I gave up on the attempt.

Since https://gerrit.wikimedia.org/r/c/mediawiki/core/+/711214 there is a warning about arrays on WebRequest::getVal that arrays are not used. So it could be valid to add an warning to WebRequest::getArray that only lists or one-dim arrays are used.

See https://gerrit.wikimedia.org/r/c/mediawiki/core/+/851136 / T321471 for another area with array query parameters

I was reminded of this task by @LucasWerkmeister's T367671 (non-security bug with the same root cause).

It seems the original reproduction steps no longer work since rMW6a20dc29aeef: editpage: Split off producing edit intro messages and preloaded content (it throws "Wikimedia\Assert\ParameterElementTypeException: Bad value for parameter $preloadParams: all elements must be string"), but the root cause is not fixed, and it could be exploitable in some other way still.

Also, the work I'm doing in https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1007693, if I manage to complete it, will be a fix pretty close to the root cause (the Message class will no longer recognize funny associative arrays as valid parameters).

Also, the work I'm doing in https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1007693, if I manage to complete it, will be a fix pretty close to the root cause (the Message class will no longer recognize funny associative arrays as valid parameters).

This was done in October, in time for MW 1.43 release. I think that completely resolves the root cause of the problem, but the change is not practical to backport.

Umherirrender claimed this task.

The problem part was the php trigger warning, that prints the inputed array and could be a security problem.
That part is fixed by change to different exception, so this task is fixed and T388945: Wikimedia\Assert\ParameterElementTypeException: Bad value for parameter $preloadParams: all elements must be string is now the next place to found a fix.

Also, the work I'm doing in https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1007693, if I manage to complete it, will be a fix pretty close to the root cause (the Message class will no longer recognize funny associative arrays as valid parameters).

This was done in October, in time for MW 1.43 release. I think that completely resolves the root cause of the problem, but the change is not practical to backport.

Given the above, I think this task could be made public once support for MW versions earlier than 1.43 is dropped. The last one is the 1.39 LTS, with end-of-life planned for December (https://www.mediawiki.org/wiki/Version_lifecycle). @sbassett Any advice for how to tag this so that we don't forget to do that?

Given the above, I think this task could be made public once support for MW versions earlier than 1.43 is dropped. The last one is the 1.39 LTS, with end-of-life planned for December (https://www.mediawiki.org/wiki/Version_lifecycle). @sbassett Any advice for how to tag this so that we don't forget to do that?

The next core/bundled security release (T397766) is due out in a week or two. The one after that should be due out at the end of December, when 1.39 will be dropped as a supported release. So it would probably make sense if, when @Reedy creates the next set of release tracking tasks within Phabricator, that we set this task as a subtask of the tracking task in that hierarchy.

Per above, I think this task can be made public now.

sbassett triaged this task as Medium priority.Jan 20 2026, 3:31 PM
sbassett changed Author Affiliation from N/A to Wikimedia Communities.
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 Medium.