-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
Bug Report
Describe the current behavior:
When --user is not specified, the Admin context (php/WP_CLI/Context/Admin.php:56) falls back to user ID 1:
// TODO: Add logic to find an administrator user.
$admin_user_id = 1;On multisite, user ID 1 may not be a super admin (or may not exist at all). This causes commands to silently fail because WordPress core's map_meta_cap() returns do_not_allow for these operations when the current user is not a super admin.
This affects even read-only commands like wp plugin list, because --context=auto now loads the admin environment via wp-admin/plugins.php, which gates access on activate_plugins (line 12). A non-super-admin user on multisite may lack this capability entirely, depending on whether manage_network_plugins is required.
Affected capabilities on multisite (from wp-includes/capabilities.php):
activate_plugins— required just to view the plugins pageinstall_plugins,update_plugins,delete_plugins,upload_pluginsinstall_themes,update_themes,delete_themes,upload_themesedit_plugins,edit_themes,edit_filesupdate_coreinstall_languages,update_languagesdelete_user,delete_userscreate_users(unlessadd_new_userssite option is set)
Describe the expected behavior:
When no --user is specified and the Admin context is active, WP-CLI should resolve a suitable super admin user on multisite, or a regular administrator on single-site. This aligns with the existing TODO in the code and the principle that CLI tools should work with sensible defaults.
The --user flag already allows impersonating any user, so auto-resolving a super admin does not introduce a new security surface — CLI access already implies full system access.
Steps to reproduce:
- Set up a WordPress multisite
- Ensure user ID 1 is not a super admin (
wp super-admin remove <user-1-login>) - Run
wp plugin list(without--user) - The command fails or returns incomplete results due to capability checks
- Similarly,
wp plugin install hello-dollyfails silently
Environment:
- OS: any
- Shell: any
- WP-CLI: main branch (post-Fix admin_init/init executed in reverse order and wrong user logged in #6011 merge)
- WordPress: multisite
Proposed approach:
Replace the hardcoded fallback with logic that queries get_super_admins() (multisite) or finds a user with the administrator role (single-site). Something like:
if ( is_multisite() ) {
$super_admins = get_super_admins();
if ( ! empty( $super_admins ) ) {
$admin_user = get_user_by( 'login', $super_admins[0] );
if ( $admin_user ) {
$admin_user_id = $admin_user->ID;
}
}
} else {
$admins = get_users( array( 'role' => 'administrator', 'number' => 1, 'orderby' => 'ID', 'order' => 'ASC' ) );
if ( ! empty( $admins ) ) {
$admin_user_id = $admins[0]->ID;
}
}If no suitable user is found, WP-CLI should emit a clear error: Error: No super admin user found. Specify one with --user=<login>.
Related issues:
- context=admin executes admin_init before anything on init is executed potentially causing fatal errors #6010 — noted the hardcoded user ID 1 as problematic (fix in Fix admin_init/init executed in reverse order and wrong user logged in #6011 addressed hook ordering but not this fallback)
- Set default context to "auto" #6252 / Set default context to "auto" #6255 — changed default context to
auto, making this fallback more impactful since plugin/theme commands now use admin context by default - wp core multisite-install doesn't add --admin_user to site_admin #3411 — multisite install not adding admin to
site_admins, which compounds this problem