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
This commit is contained in:
Dayllan Maza 2025-06-25 15:26:39 -04:00 committed by Reedy
parent 9ffec9dc56
commit 87ea0c739f
2 changed files with 33 additions and 0 deletions

View file

@ -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' )
);

View file

@ -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();