From dc8fe4120968b821a1d57bc572f12d865686faf7 Mon Sep 17 00:00:00 2001 From: David Cavins Date: Mon, 6 Jul 2026 14:24:59 -0500 Subject: [PATCH] Components: Restrict updates to site admins (pre-bp15 branch). Ensure that the current user has the `manage_options` capability before allowing them to change BuddyPress component status. Special thanks to kasthelord (Lukas Collishaw) who first reported this issue responsibly. Props emaralive, jjj, renato, kasthelord (Lukas Collishaw), 1353594865qq, jeromewincek (Jerome Wincek), vvh1te3zz. --- .../class-bp-rest-components-endpoint.php | 13 ++++++++- .../testcases/components/test-controller.php | 28 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/includes/bp-components/classes/class-bp-rest-components-endpoint.php b/includes/bp-components/classes/class-bp-rest-components-endpoint.php index 713cd6dd..03416922 100644 --- a/includes/bp-components/classes/class-bp-rest-components-endpoint.php +++ b/includes/bp-components/classes/class-bp-rest-components-endpoint.php @@ -271,7 +271,18 @@ public function update_item( $request ) { * @return true|WP_Error */ public function update_item_permissions_check( $request ) { - $retval = $this->get_items_permissions_check( $request ); + $retval = new WP_Error( + 'bp_rest_authorization_required', + __( 'Sorry, you are not allowed to perform this action.', 'buddypress' ), + array( + 'status' => rest_authorization_required_code(), + ) + ); + + // Unlike `get_items`, toggling a component is an admin-only operation. + if ( bp_current_user_can( 'manage_options' ) ) { + $retval = true; + } /** * Filter the components `update_item` permissions check. diff --git a/tests/testcases/components/test-controller.php b/tests/testcases/components/test-controller.php index 1df1b093..4fd676e5 100644 --- a/tests/testcases/components/test-controller.php +++ b/tests/testcases/components/test-controller.php @@ -345,6 +345,34 @@ public function test_update_item_without_permission() { $this->assertErrorResponse( 'bp_rest_authorization_required', $response, 403 ); } + /** + * @group update_item + */ + public function test_update_item_site_admin_only() { + $u = static::factory()->user->create( + array( + 'role' => 'author', + ) + ); + + $this->bp::set_current_user( $u ); + + // Snapshot so we can prove no component was toggled. + $before = bp_get_option( 'bp-active-components' ); + + $request = new WP_REST_Request( 'PUT', $this->endpoint_url ); + $request->set_query_params( array( + 'name' => 'friends', + 'action' => 'deactivate', + ) ); + $response = $this->server->dispatch( $request ); + + $this->assertErrorResponse( 'bp_rest_authorization_required', $response, 403 ); + + // The component toggle must not have executed. + $this->assertSame( $before, bp_get_option( 'bp-active-components' ) ); + } + /** * @group delete_item */