[wp-trac] [WordPress Trac] #39839: Permissions processed differently between REST API and UI access causing 403 error

WordPress Trac noreply at wordpress.org
Fri Feb 10 17:44:19 UTC 2017


#39839: Permissions processed differently between REST API and UI access causing
403 error
--------------------------+-----------------------------
 Reporter:  reldev        |      Owner:
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  REST API      |    Version:  4.7.2
 Severity:  normal        |   Keywords:
  Focuses:                |
--------------------------+-----------------------------
 I’m testing the REST API and have discovered a problem with how the REST
 API processes permissions. I am able to create a post or page successfully
 as well as update a post or page successfully, however, attempting to
 retrieve a draft post or page I had previously created fails with a 403
 status from line 902 in class-wp-rest-server.php.

 For reference, I’m testing urls of the form:

 {{{
 http://<domain>/wp-json/wp/v2/posts/<id>
 }}}

 and

 {{{
 http://<domain>/wp-json/wp/v2/posts/<id>?context=edit
 }}}


 The reason for the failure is because the function
 get_item_permissions_check in class-wp-rest-posts-controller.php is
 returning false to class-wp-rest-server.php at the invocation on line 897.
 if $request[‘context’] is "edit", get_item_permissions_check makes a call
 to check_update_permission on line 395 (which always succeeds). It then
 makes a call to check_read_permission on line 412 and returns the return
 value of that function call to class-wp-rest-server.php. This return value
 is always false, causing class-wp-rest-server.php to fail the request with
 403 on line 902.

 check_read_permission makes a call to current_user_can on line 1274 to
 check for the read_post capability. This call eventually invokes the
 has_cap function in class-wp-user.php on line 715. “read_post” is mapped
 to a meta capability of “read” on line 723. In the subsequent check for
 “read” in all the user’s capabilities ($capabilities) on line 750, “read”
 is not found, therefore the function returns false to
 check_read_permission, which in turn, returns false to
 get_item_permissions and back to class-wp-rest-server.php as well.

 The problem appears not to be in the evaluation of the permission by
 check_read_permission and subsequently called routines, but in the
 handling of the returned value by class-wp-rest-server.php. I verified
 this by analyzing these permission checks when viewing or editing the same
 draft post from the UI.

 In this case, I logged in as the same user I’m testing with from my REST
 API test program and clicked on Edit for the post I’ve been testing with
 which evaluates to a a url of the form:

 {{{
 http://<domain>/wp-admin/post.php?post=<id>&action=edit
 }}}

 In this case, there are a couple of calls to current_user_can for
 “read_post” from various locations in the code. admin-bar.php on line 593
 makes a call to current_user_can for “read_post” and the evaluation of the
 permission from this point forward is identical to the REST-based request.
 “read_post” is mapped to a meta capability of “read” which is still not
 found in the full list of the user’s capabilities (wp-user.php line 750).
 The difference between the REST-based request and the UI request is how
 this false is ultimately handled. In the REST case, this false causes the
 request to fail with a 403. In this UI case, this false is returned to
 admin-bar.php on line 593 but processing continues. Likewise wp-
 admin->includes->post.php on line 1309 calls current_user_can for
 “read_post” and the evaluation of the permission occurs the same. In
 neither case, however, does the fact the check for the “read_post”
 capability returns false impact processing.

 In another instance, I tested from the UI with a url of the form:

 {{{
 http://<domain>/?p=<id>
 }}}

 Using this approach to preview the draft post (while logged in as the same
 user), the “read_post” capability is never checked, only “edit_post” and
 “read” in various places. In each case, “read” meta maps to “read” which
 is again never found in the user’s capabilities, however, processing
 continues and the page displays as expected.

 For reference, in either the UI or API case, the user’s full set of
 capabilities is identical as determined in has_cap on line 743 in class-
 wp-user.php:

 {{{
     [switch_themes] => 1
     [edit_themes] => 1
     [activate_plugins] => 1
     [edit_plugins] => 1
     [edit_users] => 1
     [edit_files] => 1
     [manage_options] => 1
     [moderate_comments] => 1
     [manage_categories] => 1
     [manage_links] => 1
     [upload_files] => 1
     [import] => 1
     [unfiltered_html] => 1
     [edit_posts] => 1
     [edit_others_posts] => 1
     [edit_published_posts] => 1
     [publish_posts] => 1
     [edit_pages] => 1
     [edit_others_pages] => 1
     [edit_published_pages] => 1
     [publish_pages] => 1
     [delete_pages] => 1
     [delete_others_pages] => 1
     [delete_published_pages] => 1
     [delete_posts] => 1
     [delete_others_posts] => 1
     [delete_published_posts] => 1
     [delete_private_posts] => 1
     [edit_private_posts] => 1
     [read_private_posts] => 1
     [delete_private_pages] => 1
     [edit_private_pages] => 1
     [read_private_pages] => 1
     [delete_users] => 1
     [create_users] => 1
     [unfiltered_upload] => 1
     [edit_dashboard] => 1
     [update_plugins] => 1
     [delete_plugins] => 1
     [install_plugins] => 1
     [update_themes] => 1
     [install_themes] => 1
     [update_core] => 1
     [list_users] => 1
     [remove_users] => 1
     [promote_users] => 1
     [edit_theme_options] => 1
     [delete_themes] => 1
     [export] => 1
     [frm_view_forms] => 1
     [frm_edit_forms] => 1
     [frm_delete_forms] => 1
     [frm_change_settings] => 1
     [frm_view_entries] => 1
     [frm_delete_entries] => 1
     [email_users_notify] => 1
     [email_single_user] => 1
     [email_multiple_users] => 1
     [email_user_groups] => 1
     [administrator] => 1
     [edit_wp-rest-api-logs] => 1
     [delete_wp-rest-api-logs] => 1
     [read_wp-rest-api-log] => 1
     [edit_wp-rest-api-log] => 1
     [delete_wp-rest-api-log] => 1
 }}}

 In summary, I’m not sure what the call to check_read_permission in class-
 wp-rest-posts-controller.php is intended to accomplish, but the meta
 capability of “read” (mapped from “read_post”) is never present in the
 user’s capabilities in my testing, failing every request to read a draft
 post via the REST API. “read” is also never present when accessing this
 draft post from the UI, but processing continues as expected.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/39839>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list