Skip to content

Conversation

@Ref34t
Copy link
Contributor

@Ref34t Ref34t commented Sep 30, 2025

Summary

Changes Made

Documentation Improvements

  • docs/2.getting-started.md: Replaced 22-line manual permission checking example with clean 8-line execute() pattern
  • docs/4.using-abilities.md: Eliminated manual permission checking anti-patterns, added advanced error handling section showing how to handle specific error types

REST API Controller Update

  • includes/rest-api/endpoints/class-wp-rest-abilities-run-controller.php: Updated permission check to use strict comparison (true !==) for consistency with execute() pattern

Discussion Point

As @gziolo noted, this isn't a security vulnerability since each ability's execute() method already performs comprehensive permission checking. The REST API controller creates a two-layer permission model:

  1. REST API layer: Pre-check via run_ability_permissions_check()
  2. Ability execution layer: Full check via execute()

The controller's permission callback is architecturally unique because it dynamically checks permissions for any ability. We could consider simplifying by removing the separate permission callback and relying entirely on execute()'s error handling.

Open to feedback on this approach.

Test plan

  • Verify documentation examples follow recommended execute() pattern
  • Confirm no manual permission checking anti-patterns remain in docs
  • Test REST API endpoint permission handling

@github-actions
Copy link

github-actions bot commented Sep 30, 2025

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.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @mohamed.khaled@9hdigital.com.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: mohamed.khaled@9hdigital.com.

Co-authored-by: justlevine <justlevine@git.wordpress.org>
Co-authored-by: Ref34t <mokhaled@git.wordpress.org>
Co-authored-by: felixarntz <flixos90@git.wordpress.org>
Co-authored-by: jonathanbossenger <psykro@git.wordpress.org>
Co-authored-by: gziolo <gziolo@git.wordpress.org>

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

@codecov
Copy link

codecov bot commented Sep 30, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.20%. Comparing base (9da857e) to head (27b7b1a).

Additional details and impacted files
@@             Coverage Diff              @@
##              trunk      #95      +/-   ##
============================================
+ Coverage     90.59%   94.20%   +3.60%     
============================================
  Files            20        7      -13     
  Lines          1489      328    -1161     
  Branches        117      116       -1     
============================================
- Hits           1349      309    -1040     
+ Misses          140       19     -121     
Flag Coverage Δ
javascript 94.20% <ø> (ø)
unit ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gziolo
Copy link
Member

gziolo commented Sep 30, 2025

REST API security vulnerability

I don't think we are really experiencing a security vulnerability here, because every ability handles permissions check individually during execution as discussed in #76 (comment). That being said, we can iterate on the handling because the run controller is unique, as its permissions check model differs for each ability.

@gziolo gziolo added the [Type] Bug Something isn't working label Sep 30, 2025
@gziolo
Copy link
Member

gziolo commented Oct 1, 2025

This PR needs a rebase to resolve conflicts after #94 landed. This would help to review the changes proposed in this PR.

@Ref34t
Copy link
Contributor Author

Ref34t commented Oct 1, 2025

@gziolo on it

Mohamed Khaled added 3 commits October 1, 2025 11:03
… examples

- Eliminate all manual permission checking examples that could lead to security vulnerabilities
- Add advanced error handling section with specific error code handling
- Update variable names for consistency across examples
- Address @justlevine's feedback about documentation anti-patterns
Change permission check from loose to strict comparison in run_ability_permissions_check().
The previous pattern `if ( ! $ability->check_permission( $input ) )` would incorrectly
pass WP_Error objects as truthy, potentially allowing unauthorized access.

Fixed by using `if ( true !== $ability->check_permission( $input ) )` to properly
handle both false and WP_Error return values.
The strict permission checking now correctly catches input validation
failures in the permission check phase, returning 403 instead of
allowing invalid requests to proceed to execution-specific validation.

Updated 4 failing tests to expect 403 status and appropriate error codes:
- test_resource_ability_requires_get
- test_get_request_with_non_array_input
- test_post_request_with_non_array_input
- test_input_validation_failure_returns_error
@Ref34t Ref34t force-pushed the feature/fix-documentation-clean branch from 9df7d76 to bb906c3 Compare October 1, 2025 08:05
@Ref34t Ref34t changed the title Fix documentation anti-patterns and REST API security vulnerability docs: Improve permission checking documentation and examples Oct 1, 2025
@Ref34t
Copy link
Contributor Author

Ref34t commented Oct 1, 2025

I've updated the PR title and description - you're right that this isn't a security vulnerability.

The reason: even if the REST API permission check had the WP_Error truthiness issue, execute() on line 136 would still block unauthorized access since it performs its own permission check internally.

This update improves code correctness by using strict comparison (true !==) to properly handle all return types from check_permissions(), but it's not fixing an actual security hole due to the two-layer permission model.

@jonathanbossenger
Copy link
Contributor

I'm in the process of updating documentation in preparation for the 6.9 merge request in #117, so once that's merged, I'll come back here to check what still needs to be included.


$input = $this->get_input_from_request( $request );
if ( ! $ability->check_permissions( $input ) ) {
if ( true !== $ability->check_permissions( $input ) ) {
Copy link
Member

Choose a reason for hiding this comment

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

Sharing relevant feedback that I initially mentioned in WordPress/wordpress-develop#9410 (comment): I don't think we should replace a contextually more specific error (from the actual permission callback) with a generic "Sorry you can't do this" error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch! I've updated the code to preserve specific error messages from the permission callback instead of replacing them with a generic error.

The permission check now:

  1. Returns the WP_Error directly if check_permissions() returns one (preserves context)
  2. Only falls back to the generic error if it returns false

resolved here https://github.com/WordPress/abilities api/pull/95/commits/27b7b1a8215023b128cbcc55a27f51ac23e8774c

Copy link
Contributor

@jonathanbossenger jonathanbossenger left a comment

Choose a reason for hiding this comment

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

Some minor documentation suggestions.

Also, the docs folder structure has been updated in #117, so you might have to fetch those updates.

Mohamed Khaled added 2 commits October 23, 2025 10:11
Don't replace contextually specific errors from check_permissions() with
generic 'Sorry, you are not allowed' error. If check_permissions() returns
a WP_Error, preserve and return it directly. Only use generic error as
fallback when permission check returns false.
@gziolo
Copy link
Member

gziolo commented Oct 24, 2025

It looks like the changes applied in this PR after the rebase are no longer visible. @Ref34t, is there still anything we should fix in the docs? All the issues raised for the permission checks in the code were fixed during merge to WordPress core, and they are now being synced with #126.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Bug Something isn't working

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

5 participants