Page MenuHomePhabricator

CVE-2025-67480: list=allrevisions can be used to bypass Extension:Lockdown
Closed, ResolvedPublicSecurity

Description

The allrevisions list (and all other lists inheriting from ApiQueryRevisionsBase) in the action=query module can be used to retrieve the contents of pages that are protected by the Lockdown extension and added to $wgNonincludableNamespaces.
This is a similar issue to T397521.

Reproduction

  1. Install Lockdown and add the following to your LocalSettings.php:
$wgNamespacePermissionLockdown[NS_PROJECT]['read'] = [ 'sysop' ];
$wgNonincludableNamespaces[] = NS_PROJECT;
  1. Create a page in the project namespace
  2. Make sure you're logged out or don't have sysop perms (trying to access the page should yield a "Login required" page
  3. Go to /wiki/Special:ApiSandbox#action=query&format=json&list=allrevisions&titles=&formatversion=2&arvprop=content&arvnamespace=4

The API returns the content of the read-protected page, for example:

{
    "batchcomplete": true,
    "warnings": {
        "main": {
            "warnings": "Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/postorius/lists/mediawiki-api-announce.lists.wikimedia.org/> for notice of API deprecations and breaking changes."
        },
        "allrevisions": {
            "warnings": "Because \"arvslots\" was not specified, a legacy format has been used for the output. This format is deprecated, and in the future the new format will always be used."
        }
    },
    "query": {
        "allrevisions": [
            {
                "pageid": 15,
                "revisions": [
                    {
                        "contentformat": "text/x-wiki",
                        "contentmodel": "wikitext",
                        "content": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.\nTest"
                    },
                    {
                        "contentformat": "text/x-wiki",
                        "contentmodel": "wikitext",
                        "content": "Test"
                    }
                ],
                "ns": 4,
                "title": "TestWiki:LockdownTest"
            }
        ]
    }
}

Cause

One of the issues might be caused by this function:

https://gerrit.wikimedia.org/g/mediawiki/core/+/3bcd1b60ccc7e5bb36235c2df5c0e2974c48ebd8/includes/api/ApiQueryRevisionsBase.php#637

Adding $this->checkTitleUserPermissions( $title, 'read' ); after $title is created fixes the issue for me, but it also causes all queries with list=allrevision that would return at least one protected page to fully fail instead of just skipping over the page if the user doesn't have permission to read it.

Another permission check is missing here:

https://gerrit.wikimedia.org/g/mediawiki/core/+/3bcd1b60ccc7e5bb36235c2df5c0e2974c48ebd8/includes/api/ApiQueryRevisionsBase.php#541

Additional information

Event Timeline

Patch suggestion:


(As mentioned in the task description already, this causes all queries with list=allrevision that would return at least one protected page to fully fail instead of just skipping over the page if the user doesn't have permission to read it, so there's probably a better way to fix this vulnerability)

sbassett changed the task status from Open to In Progress.Aug 11 2025, 4:49 PM
sbassett assigned this task to Catrope.
sbassett triaged this task as Medium priority.
sbassett moved this task from Incoming to In Progress on the Security-Team board.
sbassett added a project: SecTeam-Processed.
This comment was removed by Catrope.

Updated patch:

This drops the restricted content from the output, rather than throwing an error. Unauthorized users will still be able to see the existence of restricted titles and revisions (as they already can through prop=revisions for example), but the "content" field will be omitted for those revisions.

I think it makes sense to throw an error when the content of a restricted page is explicitly requested (like through prop=revisions&rvprop=content&titles=Restricted_page), but it doesn't make sense to do that in a module that enumerates all revisions and just happens to list a restricted page. Just omitting the content in that case is more graceful.

Updated patch:

This drops the restricted content from the output, rather than throwing an error. Unauthorized users will still be able to see the existence of restricted titles and revisions (as they already can through prop=revisions for example), but the "content" field will be omitted for those revisions.

I think it makes sense to throw an error when the content of a restricted page is explicitly requested (like through prop=revisions&rvprop=content&titles=Restricted_page), but it doesn't make sense to do that in a module that enumerates all revisions and just happens to list a restricted page. Just omitting the content in that case is more graceful.

Deployed

Mstyles added a parent task: Restricted Task.Nov 10 2025, 10:50 PM
Mstyles moved this task from Security Patch To Deploy to Watching on the Security-Team board.
Reedy renamed this task from list=allrevisions can be used to bypass Extension:Lockdown to CVE-2025-67480: list=allrevisions can be used to bypass Extension:Lockdown.Dec 8 2025, 5:54 PM

Change #1217286 had a related patch set uploaded (by Reedy; author: Catrope):

[mediawiki/core@REL1_39] SECURITY: Check read permissions in ApiQueryRevisionsBase

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

Change #1217298 had a related patch set uploaded (by Reedy; author: Catrope):

[mediawiki/core@REL1_43] SECURITY: Check read permissions in ApiQueryRevisionsBase

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

Change #1217310 had a related patch set uploaded (by Reedy; author: Catrope):

[mediawiki/core@REL1_44] SECURITY: Check read permissions in ApiQueryRevisionsBase

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

Change #1217327 had a related patch set uploaded (by Reedy; author: Catrope):

[mediawiki/core@REL1_45] SECURITY: Check read permissions in ApiQueryRevisionsBase

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

Change #1217336 had a related patch set uploaded (by Reedy; author: Catrope):

[mediawiki/core@master] SECURITY: Check read permissions in ApiQueryRevisionsBase

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

Change #1217298 merged by jenkins-bot:

[mediawiki/core@REL1_43] SECURITY: Check read permissions in ApiQueryRevisionsBase

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

Change #1217310 merged by jenkins-bot:

[mediawiki/core@REL1_44] SECURITY: Check read permissions in ApiQueryRevisionsBase

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

Change #1217286 merged by jenkins-bot:

[mediawiki/core@REL1_39] SECURITY: Check read permissions in ApiQueryRevisionsBase

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

Change #1217327 merged by jenkins-bot:

[mediawiki/core@REL1_45] SECURITY: Check read permissions in ApiQueryRevisionsBase

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

Change #1217336 merged by jenkins-bot:

[mediawiki/core@master] SECURITY: Check read permissions in ApiQueryRevisionsBase

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

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.
sbassett removed a subscriber: Jly.