[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