Page MenuHomePhabricator

Expectation (readQueryTime <= 5) by MediaWiki\Actions\ActionEntryPoint::execute not met (actual: {actualSeconds}) in trx #{trxId}:{query}
Closed, ResolvedPublicSecurity

Description

Error
  • mwversion: 1.46.0-wmf.24
  • timestamp: 2026-04-16T20:25:37.270Z
  • phpversion: 8.3.30
  • reqId: 334fd8a4-7990-4e76-8ff5-384bd54c8710
  • Find reqId in Logstash
normalized_message
Expectation (readQueryTime <= 5) by MediaWiki\Actions\ActionEntryPoint::execute not met (actual: {actualSeconds}) in trx #{trxId}:
{query}
FrameLocationCall
from/srv/mediawiki/php-1.46.0-wmf.24/includes/libs/Rdbms/TransactionProfiler.php(569)
#0/srv/mediawiki/php-1.46.0-wmf.24/includes/libs/Rdbms/TransactionProfiler.php(375)Wikimedia\Rdbms\TransactionProfiler->reportExpectationViolated(string, Wikimedia\Rdbms\GeneralizedSql, float, string, string)
#1/srv/mediawiki/php-1.46.0-wmf.24/includes/libs/Rdbms/Database/TransactionManager.php(571)Wikimedia\Rdbms\TransactionProfiler->recordQueryCompletion(Wikimedia\Rdbms\GeneralizedSql, float, bool, int, string, string)
#2/srv/mediawiki/php-1.46.0-wmf.24/includes/libs/Rdbms/Database/Database.php(850)Wikimedia\Rdbms\TransactionManager->recordQueryCompletion(Wikimedia\Rdbms\GeneralizedSql, float, bool, int, string)
#3/srv/mediawiki/php-1.46.0-wmf.24/includes/libs/Rdbms/Database/Database.php(708)Wikimedia\Rdbms\Database->attemptQuery(Wikimedia\Rdbms\Query, string, bool)
#4/srv/mediawiki/php-1.46.0-wmf.24/includes/libs/Rdbms/Database/Database.php(635)Wikimedia\Rdbms\Database->executeQuery(Wikimedia\Rdbms\Query, string, int)
#5/srv/mediawiki/php-1.46.0-wmf.24/includes/libs/Rdbms/Database/Database.php(1368)Wikimedia\Rdbms\Database->query(Wikimedia\Rdbms\Query, string)
#6/srv/mediawiki/php-1.46.0-wmf.24/includes/libs/Rdbms/Database/DBConnRef.php(129)Wikimedia\Rdbms\Database->select(array, array, array, string, array, array)
#7/srv/mediawiki/php-1.46.0-wmf.24/includes/libs/Rdbms/Database/DBConnRef.php(386)Wikimedia\Rdbms\DBConnRef->__call(string, array)
#8/srv/mediawiki/php-1.46.0-wmf.24/includes/libs/Rdbms/QueryBuilder/SelectQueryBuilder.php(761)Wikimedia\Rdbms\DBConnRef->select(array, array, array, string, array, array)
#9/srv/mediawiki/php-1.46.0-wmf.24/includes/Pager/IndexPager.php(468)Wikimedia\Rdbms\SelectQueryBuilder->fetchResultSet()
#10/srv/mediawiki/php-1.46.0-wmf.24/includes/Specials/Pager/ImageListPager.php(410)MediaWiki\Pager\IndexPager->reallyDoQuery(string, int, bool)
#11/srv/mediawiki/php-1.46.0-wmf.24/includes/Pager/IndexPager.php(259)MediaWiki\Specials\Pager\ImageListPager->reallyDoQuery(string, int, bool)
#12/srv/mediawiki/php-1.46.0-wmf.24/includes/Pager/IndexPager.php(891)MediaWiki\Pager\IndexPager->doQuery()
#13/srv/mediawiki/php-1.46.0-wmf.24/includes/Pager/TablePager.php(276)MediaWiki\Pager\IndexPager->isNavigationBarShown()
#14/srv/mediawiki/php-1.46.0-wmf.24/includes/Pager/TablePager.php(85)MediaWiki\Pager\TablePager->getNavigationBar()
#15/srv/mediawiki/php-1.46.0-wmf.24/includes/Specials/SpecialListFiles.php(94)MediaWiki\Pager\TablePager->getFullOutput()
#16/srv/mediawiki/php-1.46.0-wmf.24/includes/SpecialPage/SpecialPage.php(729)MediaWiki\Specials\SpecialListFiles->execute(null)
#17/srv/mediawiki/php-1.46.0-wmf.24/includes/SpecialPage/SpecialPageFactory.php(1714)MediaWiki\SpecialPage\SpecialPage->run(null)
#18/srv/mediawiki/php-1.46.0-wmf.24/includes/Actions/ActionEntryPoint.php(505)MediaWiki\SpecialPage\SpecialPageFactory->executePath(string, MediaWiki\Context\RequestContext)
#19/srv/mediawiki/php-1.46.0-wmf.24/includes/Actions/ActionEntryPoint.php(145)MediaWiki\Actions\ActionEntryPoint->performRequest()
#20/srv/mediawiki/php-1.46.0-wmf.24/includes/MediaWikiEntryPoint.php(180)MediaWiki\Actions\ActionEntryPoint->execute()
#21/srv/mediawiki/php-1.46.0-wmf.24/index.php(44)MediaWiki\MediaWikiEntryPoint->run()
#22/srv/mediawiki/w/index.php(3)require(string)
#23{main}
Impact
Notes

Details

Risk Rating
High
Author Affiliation
Wikimedia Communities
Request URL
https://en.wikipedia.org/wiki/Special:ListFiles
Related Changes in Gerrit:

Related Objects

View Standalone Graph
This task is connected to more than 200 other tasks. Only direct parents and subtasks are shown here. Use View Standalone Graph to show more of the graph.

Event Timeline

Zabe set Security to Software security bug.EditedApr 16 2026, 8:32 PM
Zabe added projects: Security, Security-Team.
Zabe changed the visibility from "Public (No Login Required)" to "Custom Policy".
Zabe changed the subtype of this task from "Production Error" to "Security Issue".

This is so bad, it could easily be exploided as a DOS vector. Reproducable by visiting https://en.wikipedia.org/wiki/Special:ListFiles.

wikiadmin2023@10.64.0.172(enwiki)> explain SELECT  fr_timestamp,file_name,fr_size,CASE WHEN file_latest = fr_id THEN 'yes' ELSE 'no' END AS `top`,comment_fr_description.comment_text AS `fr_description_text`,comment_fr_description.comment_data AS `fr_description_data`,comment_fr_description.comment_id AS `fr_description_cid`,'fr_description' AS `description_field`,actor_user,actor_name  FROM `file` JOIN `filerevision` ON ((fr_file=file_id)) JOIN `actor` ON ((actor_id=fr_actor)) JOIN `comment` `comment_fr_description` ON ((comment_fr_description.comment_id = fr_description_id))   WHERE file_deleted = 0 AND fr_deleted = 0 AND (file_latest = fr_id)  ORDER BY fr_timestamp DESC,file_name DESC LIMIT 51  ;
+------+-------------+------------------------+--------+------------------------------------+---------+---------+---------------------------------------+--------+----------------------------------------------+
| id   | select_type | table                  | type   | possible_keys                      | key     | key_len | ref                                   | rows   | Extra                                        |
+------+-------------+------------------------+--------+------------------------------------+---------+---------+---------------------------------------+--------+----------------------------------------------+
|    1 | SIMPLE      | file                   | ALL    | PRIMARY,file_latest                | NULL    | NULL    | NULL                                  | 985386 | Using where; Using temporary; Using filesort |
|    1 | SIMPLE      | filerevision           | eq_ref | PRIMARY,fr_actor_timestamp,fr_file | PRIMARY | 8       | enwiki.file.file_latest               | 1      | Using where                                  |
|    1 | SIMPLE      | actor                  | eq_ref | PRIMARY                            | PRIMARY | 8       | enwiki.filerevision.fr_actor          | 1      |                                              |
|    1 | SIMPLE      | comment_fr_description | eq_ref | PRIMARY                            | PRIMARY | 8       | enwiki.filerevision.fr_description_id | 1      |                                              |
+------+-------------+------------------------+--------+------------------------------------+---------+---------+---------------------------------------+--------+----------------------------------------------+
4 rows in set (0.001 sec)

wikiadmin2023@10.64.0.172(enwiki)>

This is how the read old query looks like.

wikiadmin2023@10.64.16.22(enwiki)> explain SELECT  img_timestamp,img_name,img_size,'yes' AS `top`,comment_img_description.comment_text AS `img_description_text`,comment_img_description.comment_data AS `img_description_data`,comment_img_description.comment_id AS `img_description_cid`,'img_description' AS `description_field`,actor_user,actor_name  FROM `image` JOIN `actor` ON ((actor_id=img_actor)) JOIN `comment` `comment_img_description` ON ((comment_img_description.comment_id = img_description_id))    ORDER BY img_timestamp DESC,img_name DESC LIMIT 51  ;
+------+-------------+-------------------------+--------+---------------------+---------------+---------+---------------------------------+------+-------+
| id   | select_type | table                   | type   | possible_keys       | key           | key_len | ref                             | rows | Extra |
+------+-------------+-------------------------+--------+---------------------+---------------+---------+---------------------------------+------+-------+
|    1 | SIMPLE      | image                   | index  | img_actor_timestamp | img_timestamp | 14      | NULL                            | 51   |       |
|    1 | SIMPLE      | actor                   | eq_ref | PRIMARY             | PRIMARY       | 8       | enwiki.image.img_actor          | 1    |       |
|    1 | SIMPLE      | comment_img_description | eq_ref | PRIMARY             | PRIMARY       | 8       | enwiki.image.img_description_id | 1    |       |
+------+-------------+-------------------------+--------+---------------------+---------------+---------+---------------------------------+------+-------+
3 rows in set (0.001 sec)

wikiadmin2023@10.64.16.22(enwiki)>

@Ladsgroup

The fix is similar to https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1270055. IMO it should be fine to push it through gerrit.

LGTM. My only concern is about straight join since it allows for filtering based on username[1] so in some cases actor should be the first table and straight join could break things. Would you mind testing the patch in mw-experimental? If it doesn't break the join order on those cases, consider it a +2 from my side.

[1] That filtering doesn't make sense. https://test.wikipedia.org/wiki/Special:NewFiles?user=Ladsgroup is the same as https://test.wikipedia.org/wiki/Special:ListFiles/Ladsgroup future-me problem.

I also agree a patch in gerrit with an innocuous message ("improving performance") is okay.

I also agree a patch in gerrit with an innocuous message ("improving performance") is okay.

+1

LGTM. My only concern is about straight join since it allows for filtering based on username[1] so in some cases actor should be the first table and straight join could break things. Would you mind testing the patch in mw-experimental? If it doesn't break the join order on those cases, consider it a +2 from my side.

Sure. It seems fine. I am only straight joining the file table, so case of doing a user filter, it still queries the actor table first.

e.g. the query for https://en.wikipedia.org/wiki/Special:ListFiles?limit=50&user=Ladsgroup using the patch:

wikiadmin2023@10.64.16.22(enwiki)> explain SELECT  fr_timestamp,file_name,fr_id,fr_size,CASE WHEN file_latest = fr_id THEN 'yes' ELSE 'no' END AS `top`,comment_fr_description.comment_text AS `fr_description_text`,comment_fr_description.comment_data AS `fr_description_data`,comment_fr_description.comment_id AS `fr_description_cid`,'fr_description' AS `description_field`,actor_user,actor_name  FROM `filerevision` STRAIGHT_JOIN `file` ON ((fr_file=file_id)) JOIN `actor` ON ((actor_id=fr_actor)) JOIN `comment` `comment_fr_description` ON ((comment_fr_description.comment_id = fr_description_id))   WHERE file_deleted = 0 AND fr_deleted = 0 AND actor_name = 'Ladsgroup' AND (file_latest = fr_id)  ORDER BY fr_timestamp DESC,fr_id DESC LIMIT 51  ;
+------+-------------+------------------------+--------+------------------------------------+--------------------+---------+---------------------------------------+------+-------------+
| id   | select_type | table                  | type   | possible_keys                      | key                | key_len | ref                                   | rows | Extra       |
+------+-------------+------------------------+--------+------------------------------------+--------------------+---------+---------------------------------------+------+-------------+
|    1 | SIMPLE      | actor                  | const  | PRIMARY,actor_name                 | actor_name         | 257     | const                                 | 1    |             |
|    1 | SIMPLE      | filerevision           | ref    | PRIMARY,fr_actor_timestamp,fr_file | fr_actor_timestamp | 8       | const                                 | 4    | Using where |
|    1 | SIMPLE      | file                   | eq_ref | PRIMARY,file_latest                | PRIMARY            | 8       | enwiki.filerevision.fr_file           | 1    | Using where |
|    1 | SIMPLE      | comment_fr_description | eq_ref | PRIMARY                            | PRIMARY            | 8       | enwiki.filerevision.fr_description_id | 1    |             |
+------+-------------+------------------------+--------+------------------------------------+--------------------+---------+---------------------------------------+------+-------------+
4 rows in set (0.001 sec)

wikiadmin2023@10.64.16.22(enwiki)>

But I found a different issue, when going to https://en.wikipedia.org/wiki/Special:ListFiles?limit=50&user=&ilshowall=1 using the patch:

wikiadmin2023@10.64.16.22(enwiki)> explain SELECT  fr_timestamp,file_name,fr_id,fr_size,CASE WHEN file_latest = fr_id THEN 'yes' ELSE 'no' END AS `top`,comment_fr_description.comment_text AS `fr_description_text`,comment_fr_description.comment_data AS `fr_description_data`,comment_fr_description.comment_id AS `fr_description_cid`,'fr_description' AS `description_field`,actor_user,actor_name  FROM `filerevision` STRAIGHT_JOIN `file` ON ((fr_file=file_id)) JOIN `actor` ON ((actor_id=fr_actor)) JOIN `comment` `comment_fr_description` ON ((comment_fr_description.comment_id = fr_description_id))   WHERE file_deleted = 0 AND fr_deleted = 0  ORDER BY file_name DESC LIMIT 51  ;
+------+-------------+------------------------+--------+----------------------------+---------+---------+---------------------------------------+---------+----------------------------------------------+
| id   | select_type | table                  | type   | possible_keys              | key     | key_len | ref                                   | rows    | Extra                                        |
+------+-------------+------------------------+--------+----------------------------+---------+---------+---------------------------------------+---------+----------------------------------------------+
|    1 | SIMPLE      | filerevision           | ALL    | fr_actor_timestamp,fr_file | NULL    | NULL    | NULL                                  | 1363393 | Using where; Using temporary; Using filesort |
|    1 | SIMPLE      | file                   | eq_ref | PRIMARY                    | PRIMARY | 8       | enwiki.filerevision.fr_file           | 1       | Using where                                  |
|    1 | SIMPLE      | actor                  | eq_ref | PRIMARY                    | PRIMARY | 8       | enwiki.filerevision.fr_actor          | 1       |                                              |
|    1 | SIMPLE      | comment_fr_description | eq_ref | PRIMARY                    | PRIMARY | 8       | enwiki.filerevision.fr_description_id | 1       |                                              |
+------+-------------+------------------------+--------+----------------------------+---------+---------+---------------------------------------+---------+----------------------------------------------+
4 rows in set (0.001 sec)

wikiadmin2023@10.64.16.22(enwiki)>

Maybe in those cases making the order be fr_file would be better? Otherwise, order should be id or timestamp.

Ok so apparently this specifically is caused by a hack to prevent slow queries in read old (https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/cf098948baef163688b3f3fa42613882c68aa07b/includes/Specials/Pager/ImageListPager.php#277) which was added due to a missing oi_timestamp index. The index then got added in T279982, but apparently no one ever remembered to remove the hack.

So I will just go ahead and disable this hack in read new. This fixes the regular query for the case described above. But it still does cause issues if the user manually sorts by the name. The issue is caused by the straight join because in this case we actually want to query the file table first. So we need to make the straight join conditional.

Change #1273011 had a related patch set uploaded (by Zabe; author: Zabe):

[mediawiki/core@master] ImageListPager: Make sure file and filerevision are in correct order

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

Change #1273011 had a related patch set uploaded (by Zabe; author: Zabe):

[mediawiki/core@master] ImageListPager: Make sure file and filerevision are in correct order

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

I tested the new patch with all combination shown above on enwiki and it seems to no longer produce bad queries.

Change #1273011 merged by jenkins-bot:

[mediawiki/core@master] ImageListPager: Make sure file and filerevision are in correct order

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

Change #1273787 had a related patch set uploaded (by Jforrester; author: Zabe):

[mediawiki/core@wmf/1.46.0-wmf.24] ImageListPager: Make sure file and filerevision are in correct order

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

Change #1273787 abandoned by Jforrester:

[mediawiki/core@wmf/1.46.0-wmf.24] ImageListPager: Make sure file and filerevision are in correct order

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

sbassett moved this task from Incoming to Our Part Is Done on the Security-Team board.

@Zabe et al - any reason to keep this task private?

@Zabe et al - any reason to keep this task private?

Nope :)

sbassett changed Author Affiliation from N/A to Wikimedia Communities.Tue, Apr 21, 5:23 PM
sbassett changed the visibility from "Custom Policy" to "Public (No Login Required)".
sbassett changed Risk Rating from N/A to High.