From e7b6f473706495c460e085c679cdaedb846d5914 Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Tue, 31 Mar 2026 15:22:54 -0400 Subject: [PATCH 1/5] PHPCS: Allowlist custom capabilities instead of disabling the sniff. Replace the blanket severity override for WordPress.WP.Capabilities.Unknown with an explicit allowlist of all custom capabilities used across the codebase. This also fixes two capability bugs surfaced by enabling the sniff: - Plugin Directory ES Status tool used the role name `plugin_admin` instead of a capability. Replace with `plugin_approve`, which is the distinguishing capability for the plugin admin role. - Plugin Directory comment row actions checked `manage_comments`, which is not a WordPress capability. Replace with `moderate_comments`. Co-Authored-By: Claude Opus 4.6 (1M context) --- phpcs.xml.dist | 80 ++++++++++++++++++- .../admin/class-customizations.php | 2 +- .../tools/class-elasticsearch-status.php | 8 +- 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index ebb2fbe37e..2374a11f62 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -119,9 +119,83 @@ 0 - - - 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/class-customizations.php b/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/class-customizations.php index 9513e2d278..63158cfedd 100644 --- a/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/class-customizations.php +++ b/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/class-customizations.php @@ -819,7 +819,7 @@ public function custom_comment_row_actions( $actions, $comment ) { if ( 'internal-note' === $comment->comment_type && isset( $_REQUEST['mode'] ) && 'single' === $_REQUEST['mode'] ) { $allowed_actions = array( 'reply' => true ); - if ( current_user_can( 'manage_comments' ) ) { + if ( current_user_can( 'moderate_comments' ) ) { $allowed_actions['trash'] = true; $allowed_actions['untrash'] = true; $allowed_actions['quickedit'] = true; diff --git a/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/tools/class-elasticsearch-status.php b/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/tools/class-elasticsearch-status.php index 244b1bcab5..0c988533bf 100644 --- a/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/tools/class-elasticsearch-status.php +++ b/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/tools/class-elasticsearch-status.php @@ -27,14 +27,14 @@ public function add_to_menu() { 'plugin-tools', 'ES Index Status', 'ES Index Status', - 'plugin_admin', + 'plugin_approve', 'es-index-status', array( $this, 'render' ) ); } public function render() { - if ( ! current_user_can( 'plugin_admin' ) ) { + if ( ! current_user_can( 'plugin_approve' ) ) { return; } @@ -249,7 +249,7 @@ function tick() { public function ajax_check_batch() { check_ajax_referer( 'es-index-check-batch' ); - if ( ! current_user_can( 'plugin_admin' ) ) { + if ( ! current_user_can( 'plugin_approve' ) ) { wp_send_json_error( 'Permission denied.' ); } @@ -294,7 +294,7 @@ public function ajax_check_batch() { public function ajax_reindex() { check_ajax_referer( 'es-index-check-batch' ); - if ( ! current_user_can( 'plugin_admin' ) ) { + if ( ! current_user_can( 'plugin_approve' ) ) { wp_send_json_error( 'Permission denied.' ); } From 0502eecd8f1e22e25280e014f4f108226e1e3039 Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Tue, 31 Mar 2026 15:44:23 -0400 Subject: [PATCH 2/5] Add missing capabilities to the allowlist and fix additional bugs. - Add singular theme caps (suspend_theme, reinstate_theme) and bbPress caps (bbp_forums_admin, edit_topic, edit_reply, read_topic) to the allowlist. - Photo Directory used the role name photos_moderator instead of a capability. Replace with edit_photos. - BuddyPress checked four role names instead of capabilities in the admin redirect. Replace with a single edit_posts check, which all contributors and above have. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../plugins/buddypress-org/buddypress-dot-org.php | 7 +------ phpcs.xml.dist | 6 ++++++ .../wp-content/plugins/photo-directory/inc/moderation.php | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/buddypress.org/public_html/wp-content/plugins/buddypress-org/buddypress-dot-org.php b/buddypress.org/public_html/wp-content/plugins/buddypress-org/buddypress-dot-org.php index c1e992264b..f1258999ec 100644 --- a/buddypress.org/public_html/wp-content/plugins/buddypress-org/buddypress-dot-org.php +++ b/buddypress.org/public_html/wp-content/plugins/buddypress-org/buddypress-dot-org.php @@ -52,12 +52,7 @@ function bporg_remove_dashboard_widget( $admin ) { * @return if user is an admin */ function bporg_admin_redirect() { - if ( is_super_admin() - || current_user_can( 'contributor' ) - || current_user_can( 'author' ) - || current_user_can( 'editor' ) - || current_user_can( 'administrator' ) - ) + if ( is_super_admin() || current_user_can( 'edit_posts' ) ) return; // Allow registered unprivileged admin-ajax.php requests for diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 2374a11f62..67ce0a3d5a 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -146,6 +146,8 @@ + + @@ -169,6 +171,10 @@ + + + + diff --git a/wordpress.org/public_html/wp-content/plugins/photo-directory/inc/moderation.php b/wordpress.org/public_html/wp-content/plugins/photo-directory/inc/moderation.php index 8dc2f4726d..a79adb96ba 100644 --- a/wordpress.org/public_html/wp-content/plugins/photo-directory/inc/moderation.php +++ b/wordpress.org/public_html/wp-content/plugins/photo-directory/inc/moderation.php @@ -291,7 +291,7 @@ public static function disable_own_post_editing( $caps, $cap, $args, $user ) { } // Bail if user isn't a moderator. - if ( ! user_can( $user->ID, 'photos_moderator' ) ) { + if ( ! user_can( $user->ID, 'edit_photos' ) ) { return $caps; } From 61daa28f871ed60971c77a4a59e6afd400307913 Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Tue, 31 Mar 2026 15:48:20 -0400 Subject: [PATCH 3/5] BuddyPress: Add braces around inline control structure. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../wp-content/plugins/buddypress-org/buddypress-dot-org.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/buddypress.org/public_html/wp-content/plugins/buddypress-org/buddypress-dot-org.php b/buddypress.org/public_html/wp-content/plugins/buddypress-org/buddypress-dot-org.php index f1258999ec..b78c580c21 100644 --- a/buddypress.org/public_html/wp-content/plugins/buddypress-org/buddypress-dot-org.php +++ b/buddypress.org/public_html/wp-content/plugins/buddypress-org/buddypress-dot-org.php @@ -52,8 +52,9 @@ function bporg_remove_dashboard_widget( $admin ) { * @return if user is an admin */ function bporg_admin_redirect() { - if ( is_super_admin() || current_user_can( 'edit_posts' ) ) + if ( is_super_admin() || current_user_can( 'edit_posts' ) ) { return; + } // Allow registered unprivileged admin-ajax.php requests for // profiles.wordpress.org to pass through. From 97d0f6a1eeabfc0f1a6536e9dd46698d90926efb Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Tue, 31 Mar 2026 15:54:00 -0400 Subject: [PATCH 4/5] Photo Directory: Use allcaps array instead of user_can in user_has_cap filter. Calling user_can() for edit_photos inside a user_has_cap filter that handles edit_photos would cause infinite recursion. Check the allcaps array directly instead. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../wp-content/plugins/photo-directory/inc/moderation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wordpress.org/public_html/wp-content/plugins/photo-directory/inc/moderation.php b/wordpress.org/public_html/wp-content/plugins/photo-directory/inc/moderation.php index a79adb96ba..21378892b3 100644 --- a/wordpress.org/public_html/wp-content/plugins/photo-directory/inc/moderation.php +++ b/wordpress.org/public_html/wp-content/plugins/photo-directory/inc/moderation.php @@ -291,7 +291,7 @@ public static function disable_own_post_editing( $caps, $cap, $args, $user ) { } // Bail if user isn't a moderator. - if ( ! user_can( $user->ID, 'edit_photos' ) ) { + if ( empty( $caps['edit_photos'] ) ) { return $caps; } From 6ee71cb7eaafd9458c7690871c20fc89aa51aba7 Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Wed, 1 Apr 2026 10:53:37 -0400 Subject: [PATCH 5/5] PHPCS: Note that custom capabilities just need documenting in the allowlist. Co-Authored-By: Claude Opus 4.6 (1M context) --- phpcs.xml.dist | 1 + 1 file changed, 1 insertion(+) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 67ce0a3d5a..784abe98ae 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -120,6 +120,7 @@ +