From 87ea0c739f61286a8499a614d4cdd114b8acdfd4 Mon Sep 17 00:00:00 2001 From: Dayllan Maza Date: Wed, 25 Jun 2025 15:26:39 -0400 Subject: [PATCH] SECURITY: Fix autoblocks visibility when bl_deleted=1 CVE-2025-6927 ApiQueryBlock was relying only on the filter returned by HideUserUtils::getExpression which only works for blocks targeting a user account Bug: T397595 Change-Id: I7bbd6ae36a11840ed6b4620b5d07fa5158ff139e --- includes/api/ApiQueryBlocks.php | 1 + .../includes/api/query/ApiQueryBlocksTest.php | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/includes/api/ApiQueryBlocks.php b/includes/api/ApiQueryBlocks.php index c1dbece8b76..570718e5cc0 100644 --- a/includes/api/ApiQueryBlocks.php +++ b/includes/api/ApiQueryBlocks.php @@ -234,6 +234,7 @@ class ApiQueryBlocks extends ApiQueryBase { } if ( !$this->getAuthority()->isAllowed( 'hideuser' ) ) { + $this->addWhere( [ 'bl_deleted' => 0 ] ); $this->addWhere( $this->hideUserUtils->getExpression( $db, 'block_target.bt_user' ) ); diff --git a/tests/phpunit/includes/api/query/ApiQueryBlocksTest.php b/tests/phpunit/includes/api/query/ApiQueryBlocksTest.php index c8ced92b95f..8ae55fec947 100644 --- a/tests/phpunit/includes/api/query/ApiQueryBlocksTest.php +++ b/tests/phpunit/includes/api/query/ApiQueryBlocksTest.php @@ -9,6 +9,7 @@ use MediaWiki\Block\Restriction\NamespaceRestriction; use MediaWiki\Block\Restriction\PageRestriction; use MediaWiki\MainConfigNames; use MediaWiki\Tests\Api\ApiTestCase; +use MediaWiki\Tests\Unit\Permissions\MockAuthorityTrait; /** * @group API @@ -18,6 +19,7 @@ use MediaWiki\Tests\Api\ApiTestCase; * @covers MediaWiki\Api\ApiQueryBlocks */ class ApiQueryBlocksTest extends ApiTestCase { + use MockAuthorityTrait; public function testExecute() { [ $data ] = $this->doApiRequest( [ @@ -81,6 +83,36 @@ class ApiQueryBlocksTest extends ApiTestCase { $this->assertArraySubmapSame( $subset, $data['query']['blocks'][0] ); } + public function testHiddenBlocksVisibility() { + // Ensure that hidden blocks are not shown by default. + $badActor = $this->getTestUser()->getUser(); + $sysop = $this->getTestSysop()->getUser(); + + $parentBlock = $this->getServiceContainer()->getDatabaseBlockStore() + ->insertBlockWithParams( [ + 'targetUser' => $badActor, + 'by' => $sysop, + 'hideName' => true, + 'enableAutoblock' => true, + ] ); + + $autoblock = $this->getServiceContainer()->getDatabaseBlockStore() + ->doAutoblock( $parentBlock, '1.2.3.4' ); + + [ $data ] = $this->doApiRequest( [ + 'action' => 'query', + 'list' => 'blocks', + ] ); + $this->assertCount( 0, $data['query']['blocks'] ); + + [ $data ] = $this->doApiRequestWithToken( [ + 'action' => 'query', + 'list' => 'blocks', + ], null, $this->mockRegisteredAuthorityWithPermissions( [ 'hideuser' ] ) ); + + $this->assertCount( 2, $data['query']['blocks'] ); + } + public function testExecuteRestrictions() { $this->overrideConfigValue( MainConfigNames::EnablePartialActionBlocks, true ); $badActor = $this->getTestUser()->getUser();