Commit de4776acd43 for woocommerce
commit de4776acd43fa87bd2ad098f1eb847b797100b62
Author: Néstor Soriano <konamiman@konamiman.com>
Date: Mon Sep 7 14:30:28 2026 +0200
Limit WooCommerce user fields in the users REST endpoint to the edit context (#68380)
The is_super_admin and woocommerce_meta fields added to the wp/v2/users
endpoint are now returned only for requests with context=edit, and only
when the current user is the requested user or has the list_users
capability. The same conditions are checked in the field callbacks.
The fields now declare a proper schema: is_super_admin is a read-only
boolean and woocommerce_meta is an object (it is an associative array,
and the array type would make updates fail validation). Remove the
related phpstan baseline entries.
diff --git a/plugins/woocommerce/changelog/pr-402-users-endpoint-field-permissions b/plugins/woocommerce/changelog/pr-402-users-endpoint-field-permissions
new file mode 100644
index 00000000000..d6d5f305829
--- /dev/null
+++ b/plugins/woocommerce/changelog/pr-402-users-endpoint-field-permissions
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Return is_super_admin and woocommerce_meta fields in users REST endpoint only for requests in 'edit' context, and only when requesting own user or with 'list_users' capability.
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index ece0f380a1a..71f8c1074a2 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -59055,12 +59055,6 @@ parameters:
count: 1
path: src/Internal/Admin/WCAdminAssets.php
- -
- message: '#^Access to offset ''id'' on an unknown class Automattic\\WooCommerce\\Internal\\Admin\\WP_User\.$#'
- identifier: class.notFound
- count: 1
- path: src/Internal/Admin/WCAdminUser.php
-
-
message: '#^Access to property \$ID on an unknown class Automattic\\WooCommerce\\Internal\\Admin\\WP_User\.$#'
identifier: class.notFound
@@ -59091,12 +59085,6 @@ parameters:
count: 1
path: src/Internal/Admin/WCAdminUser.php
- -
- message: '#^Parameter \$user of method Automattic\\WooCommerce\\Internal\\Admin\\WCAdminUser\:\:get_user_data_values\(\) has invalid type Automattic\\WooCommerce\\Internal\\Admin\\WP_User\.$#'
- identifier: class.notFound
- count: 1
- path: src/Internal/Admin/WCAdminUser.php
-
-
message: '#^Parameter \$user of method Automattic\\WooCommerce\\Internal\\Admin\\WCAdminUser\:\:update_user_data_values\(\) has invalid type Automattic\\WooCommerce\\Internal\\Admin\\WP_User\.$#'
identifier: class.notFound
diff --git a/plugins/woocommerce/src/Internal/Admin/WCAdminUser.php b/plugins/woocommerce/src/Internal/Admin/WCAdminUser.php
index 894d3a99276..6df98e4166c 100644
--- a/plugins/woocommerce/src/Internal/Admin/WCAdminUser.php
+++ b/plugins/woocommerce/src/Internal/Admin/WCAdminUser.php
@@ -41,14 +41,22 @@ class WCAdminUser {
'user',
'is_super_admin',
array(
- 'get_callback' => function( $user ) {
- if ( ! isset( $user['id'] ) || 0 === $user['id'] ) {
+ 'get_callback' => function ( $user, $attr, $request ) {
+ if ( 'edit' !== ( $request['context'] ?? null ) ) {
+ return false;
+ }
+
+ if ( ! $this->current_user_can_read_user_data( $user['id'] ?? 0 ) ) {
return false;
}
return is_super_admin( $user['id'] );
},
- 'schema' => null,
+ 'schema' => array(
+ 'type' => 'boolean',
+ 'context' => array( 'edit' ),
+ 'readonly' => true,
+ ),
)
);
register_rest_field(
@@ -57,7 +65,10 @@ class WCAdminUser {
array(
'get_callback' => array( $this, 'get_user_data_values' ),
'update_callback' => array( $this, 'update_user_data_values' ),
- 'schema' => null,
+ 'schema' => array(
+ 'type' => 'object',
+ 'context' => array( 'edit' ),
+ ),
)
);
}
@@ -66,9 +77,24 @@ class WCAdminUser {
* For all the registered user data fields ( Loader::get_user_data_fields ), fetch the data
* for returning via the REST API.
*
- * @param WP_User $user Current user.
+ * Returns an empty array unless the request has the 'edit' context and the current user
+ * is either the requested user or has the 'list_users' capability.
+ *
+ * @param array $user The prepared user data from the users endpoint response.
+ * @param mixed $attr The name of the requested field.
+ * @param \WP_REST_Request|array $request The current request.
+ *
+ * @phpstan-param \WP_REST_Request<array<string, mixed>>|array $request
*/
- public function get_user_data_values( $user ) {
+ public function get_user_data_values( $user, $attr = null, $request = array() ) {
+ if ( 'edit' !== ( $request['context'] ?? null ) ) {
+ return array();
+ }
+
+ if ( ! $this->current_user_can_read_user_data( $user['id'] ?? 0 ) ) {
+ return array();
+ }
+
$values = array();
foreach ( $this->get_user_data_fields() as $field ) {
$values[ $field ] = self::get_user_data_field( $user['id'], $field );
@@ -76,6 +102,22 @@ class WCAdminUser {
return $values;
}
+ /**
+ * Checks whether the current user is allowed to read the extra data registered by
+ * WooCommerce for a given user.
+ *
+ * @param int $user_id The id of the user whose data is being read.
+ * @return bool True if the current user can read the extra data for the given user.
+ */
+ private function current_user_can_read_user_data( $user_id ) {
+ $user_id = (int) $user_id;
+ if ( 0 === $user_id ) {
+ return false;
+ }
+
+ return get_current_user_id() === $user_id || current_user_can( 'list_users' );
+ }
+
/**
* For all the registered user data fields ( Loader::get_user_data_fields ), update the data
* for the REST API.