WordPress.org

Make WordPress Core

Opened 3 years ago

Last modified 6 weeks ago

#36056 new defect (bug)

When saving a post for an other author, the current_user_can() check is not passing the post ID with the edit_others_posts capability

Reported by: GunGeekATX Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.4.2
Component: Role/Capability Keywords:
Focuses: Cc:

Description

The scenario: we're using a custom role that is locked down to only being able to edit a single page titled 'About Us'. We've added an 'edit_about' capability to the role, and use the map_meta_cap filter to return 'edit_about' if that's the page being edited for the role.

if ( in_array( $cap, $cap_needed ) && user_can( $user_id, 'edit_about' ) && ! empty( $args ) ) {
	$post_id = $args[0];
	$page = get_post( $post_id );
	$parent = get_post( $page->post_parent );

	$caps = array();
	if ( 'page' === $page->post_type && ( 'about us' === strtolower( $page->post_title ) || ( null !== $parent && 'about us' === strtolower( $parent->post_title ) ) ) ) {
		$caps[] = 'edit_about';
	} else {
		$caps[] = 'do_not_allow';
	}
}

WP_Posts_List_Table and wp-admin/post.php is doing a simple check just on edit_post.

current_user_can( 'edit_post', $post->ID );

Because we're getting the post ID, we can allow any user with that role to see the Edit link and get to the edit page, and it's turned off for every other page.

When trying to save the post, wp-admin/includes/post.php checks to see if the author is different than the current user, but is not passing the post ID in the check:

	if ( isset( $post_data['user_ID'] ) && ( $post_data['post_author'] != $post_data['user_ID'] )
		 && ! current_user_can( $ptype->cap->edit_others_posts ) ) {
		if ( $update ) {
			if ( 'page' == $post_data['post_type'] ) {
				return new WP_Error( 'edit_others_pages', __( 'You are not allowed to edit pages as this user.' ) );
			}

Because we don't have the post ID, we don't have any context of the post being saved and are not able to tell WordPress that saving this others post is allowed. Changing the code in core above to:

current_user_can( $ptype->cap->edit_others_posts, $post_data['ID'] )

fixes the issue and allows the page to be saved. Giving the role the edit_others_pages capability also fixes the issue.

I'm not 100% sure this is a bug or by design, and may be related to #30452, but would like some input from the core team.

Change History (4)

#1 @ericlewis
3 years ago

Giving the role the edit_others_pages capability also fixes the issue.

I think this is a good way to go.

The edit_others_pages cap is intended as a generic capability to see whether a user can, at all, edit other author's pages. It seems this is a capability you want this role to have.

#2 @dd32
3 years ago

In some cases you don't want to give the edit_others_pages cap, as you don't want to allow the user to edit other users posts, just a select few you grant through edit_posts.
IMHO the checking of edit_others_pages looks, at first, to be not actually needed.. as that should really be checked through map_meta_cap() on the edit_post capability.

I ran into this exact issue yesterday, and was going to open this ticket myself. I'm unable to determine what these permission caps are for though, as the conditional post_author != user_ID means that you can take ownership of a post and skip those checks. The real checks for can this user edit this post happen higher in the chain in edit_post() (and again in _wp_translate_postdata() further up).

This ticket was mentioned in Slack in #meta by obenland. View the logs.


3 years ago

Note: See TracTickets for help on using tickets.