Skip to content

Commit a67307b

Browse files
committed
Real-time collaboration: check wp_user_id before accepting awareness update.
Using the built-in HTTP polling sync server, awareness state is accepted and stored after the user is authorized. This state is keyed against their sync client ID, which is randomly generated. However, nothing prevents a user from spoofing another client's client ID, which is discoverable by inspecting network responses. By replaying a sync request with a different client ID, they could temporarily overwrite another client's awareness state. This change prevents this spoofing by storing and checking the user's WordPress user ID to ensure it matches the initial update. Developed in: WordPress/wordpress-develop#11120. Syncs: WordPress/gutenberg#76056. Fixes #64782. Props czarate. Built from https://develop.svn.wordpress.org/trunk@61838 git-svn-id: http://core.svn.wordpress.org/trunk@61125 1a063a9b-81f0-0310-95a4-ce76da25c4cd
1 parent a1809f7 commit a67307b

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

wp-includes/collaboration/class-wp-http-polling-sync-server.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,25 @@ public function check_permissions( WP_REST_Request $request ) {
181181
);
182182
}
183183

184-
$rooms = $request['rooms'];
184+
$rooms = $request['rooms'];
185+
$wp_user_id = get_current_user_id();
185186

186187
foreach ( $rooms as $room ) {
187-
$room = $room['room'];
188+
$client_id = $room['client_id'];
189+
$room = $room['room'];
190+
191+
// Check that the client_id is not already owned by another user.
192+
$existing_awareness = $this->storage->get_awareness_state( $room );
193+
foreach ( $existing_awareness as $entry ) {
194+
if ( $client_id === $entry['client_id'] && $wp_user_id !== $entry['wp_user_id'] ) {
195+
return new WP_Error(
196+
'rest_cannot_edit',
197+
__( 'Client ID is already in use by another user.' ),
198+
array( 'status' => rest_authorization_required_code() )
199+
);
200+
}
201+
}
202+
188203
$type_parts = explode( '/', $room, 2 );
189204
$object_parts = explode( ':', $type_parts[1] ?? '', 2 );
190205

@@ -346,6 +361,7 @@ private function process_awareness_update( string $room, int $client_id, ?array
346361
'client_id' => $client_id,
347362
'state' => $awareness_update,
348363
'updated_at' => $current_time,
364+
'wp_user_id' => get_current_user_id(),
349365
);
350366
}
351367

wp-includes/version.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
* @global string $wp_version
1818
*/
19-
$wp_version = '7.0-beta2-61837';
19+
$wp_version = '7.0-beta2-61838';
2020

2121
/**
2222
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.

0 commit comments

Comments
 (0)