Skip to content

PHPCS: Allowlist custom capabilities instead of disabling the sniff#583

Open
obenland wants to merge 6 commits intoWordPress:trunkfrom
obenland:fix/phpcs-custom-capabilities
Open

PHPCS: Allowlist custom capabilities instead of disabling the sniff#583
obenland wants to merge 6 commits intoWordPress:trunkfrom
obenland:fix/phpcs-custom-capabilities

Conversation

@obenland
Copy link
Copy Markdown
Member

Summary

  • Replace the blanket <severity>0</severity> override on WordPress.WP.Capabilities.Unknown with an explicit allowlist of all custom capabilities used across the codebase, grouped by plugin.
  • Fix four capability bugs surfaced by enabling the sniff:
    • Plugin Directory: ES Status tool used the role name plugin_admin instead of a capability — replaced with plugin_approve.
    • Plugin Directory: Comment row actions checked manage_comments, which is not a WordPress capability — replaced with moderate_comments.
    • Photo Directory: Moderation used the role name photos_moderator instead of a capability — replaced with edit_photos.
    • BuddyPress: Admin redirect checked four role names (contributor, author, editor, administrator) instead of capabilities — replaced with a single edit_posts check.

Test plan

  • Run composer install && vendor/bin/phpcs --sniffs=WordPress.WP.Capabilities . and confirm no warnings or errors
  • Verify the Plugin Directory ES Index Status tool is still accessible to plugin admins
  • Verify Plugin Directory internal note comment actions still work for reviewers
  • Verify Photo Directory moderation capabilities still work for photo moderators
  • Verify BuddyPress admin redirect still allows contributors and above into wp-admin

🤖 Generated with Claude Code

obenland and others added 4 commits March 31, 2026 18:15
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) <noreply@anthropic.com>
- 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) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…p 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) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 31, 2026 22:17
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 31, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props obenland, dd32.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@obenland
Copy link
Copy Markdown
Member Author

@dd32 Wanted to give you a chance to veto. It's a long allowlist, but it enables catching misuses like the other changes in this PR.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enables the WordPress.WP.Capabilities.Unknown sniff by replacing the prior blanket suppression with an explicit allowlist of custom capabilities, and fixes several real capability/role mismatches that the sniff surfaces.

Changes:

  • Replace the PHPCS suppression of unknown capabilities with a curated custom_capabilities allowlist (grouped by subsystem).
  • Fix Plugin Directory capability checks by replacing the non-capability plugin_admin role checks with the plugin_approve capability.
  • Fix several incorrect capability/role checks (manage_comments, photos_moderator, and BuddyPress role-name checks) by switching to appropriate WordPress capabilities.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/tools/class-elasticsearch-status.php Switch ES Status tool access checks from a role name to the plugin_approve capability (menu + render + AJAX).
wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/class-customizations.php Fix internal-note comment row actions gating by using moderate_comments (valid WP cap).
wordpress.org/public_html/wp-content/plugins/photo-directory/inc/moderation.php Replace role-name moderation check with a capability-based check (edit_photos) for moderator logic.
phpcs.xml.dist Replace disabling the capability sniff with an explicit allowlist of custom capabilities for the environment.
buddypress.org/public_html/wp-content/plugins/buddypress-org/buddypress-dot-org.php Replace role-name checks with a single edit_posts capability check for wp-admin redirect UX behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


// Bail if user isn't a moderator.
if ( ! user_can( $user->ID, 'photos_moderator' ) ) {
if ( empty( $caps['edit_photos'] ) ) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs a user_can(), because super-admin roles don't have the caps.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm.. actually... this is a user_has_cap filter.. Using user_can and friends in that is discouraged in cap filters.. due to loops..

I think the proper check here would be to be either requiring a cap by appending to $caps, or appending do_not_allow to block.. or.. something.. else...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it depends on how we want this to behave. It sets edit_photos to false when the photo in question is the moderator's own photo.

If we want super admins to be able to edit their own submissions we'd append a || is_super_admin( $user->ID ) check to bail. Otherwise a && ! is_super_admin( $user->ID ) to apply to them, too?

Comment on lines +122 to +123
<!-- Custom capabilities used across the WordPress.org environment. -->
<rule ref="WordPress.WP.Capabilities">
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really a fan of this style of nitty-gritty capability listing.. but I'm not veto'ing this.

Perhaps we can do a middle-ground of warning severity or notice severity, and not error?

Let's also document it here that PRs can update the list as needed, and this isn't a strict requirement, rather just to catch those typos.

Suggested change
<!-- Custom capabilities used across the WordPress.org environment. -->
<rule ref="WordPress.WP.Capabilities">
<!-- Custom capabilities used across the WordPress.org environment. -->
<!-- Please note: Using custom capabilities is allowed, just document them here please! -->
<rule ref="WordPress.WP.Capabilities">

obenland and others added 2 commits April 1, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants