From 040a5cc0c09d43dc5f8ef178a0e0e957f4195e85 Mon Sep 17 00:00:00 2001 From: David Cavins Date: Mon, 6 Jul 2026 11:48:26 -0500 Subject: [PATCH] Components: Restrict updates to site admins (0.8 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 92c467d9..1e2e7774 100644 --- a/tests/testcases/components/test-controller.php +++ b/tests/testcases/components/test-controller.php @@ -347,6 +347,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 */