[wp-trac] [WordPress Trac] #52076: Checking anonymous user's exist capability returns inconsistent results across functions.

WordPress Trac noreply at wordpress.org
Wed Apr 7 21:50:44 UTC 2021

#52076: Checking anonymous user's exist capability returns inconsistent results
across functions.
 Reporter:  peterwilsoncc                        |       Owner:
                                                 |  peterwilsoncc
     Type:  defect (bug)                         |      Status:  reopened
 Priority:  normal                               |   Milestone:  5.8
Component:  Role/Capability                      |     Version:
 Severity:  normal                               |  Resolution:
 Keywords:  early has-patch needs-dev-note has-  |     Focuses:
  unit-tests                                     |
Changes (by juliobox):

 * status:  closed => reopened
 * resolution:  fixed =>


 Hey there, 2 things:
 **First and most important**, there is a regression with this new code.
 // Before this ticket
 user_can( 0, 'exist' ); // false
 // With this ticket
 user_can( 0, 'exist' ); // true
 The comment says "User is logged out, create anonymous user object." but
 what about a non existing user? Before the function could return "false",
 but now it's impossible to get a false with "exist".
 I've read the comment "Any check for the exist capability should return
 true because... well because. This is an anomaly which has existed since
 current_user_can() was introduced and it's been noted that some plugins
 such as BuddyPress make use of this behaviour."

 But I guess that there is also other cases with plugins doing "user_can(
 $id, 'exist' ) // false" and expecting this to be false! And this is a
 game changer now.
 I checked the wp repo and I have to admit that I didn't find even 1 plugin
 where this could cause a bug because they all check if the $user is a
 WP_User first (https://wpdirectory.net/search/01F2Q4CJTZFV747PPKFMQR5X53).
 This leads us to the second part of my comment…

 **…since we are here now**, I would like to suggest to change this:
 function user_can( $user, $capability, ...$args ) {
         if ( ! is_object( $user ) ) {
                 $user = get_userdata( $user );
 by this:
 function user_can( $user, $capability, ...$args ) {
         if ( ! is_a( $user, 'WP_User' ) ) {
                 $user = get_userdata( $user );
 to prevent this:
 $new_user = wp_insert_user( [ 'ID' => 1337 ] ); // this ID does not exist
 user_can( $new_user, 'manage_options' ); // Fatal error has_cap() method
 does not exist (or exists() method does not exist with the previous code)
 I know, I should test $user myself before inserting/updating the user.
 But like #33800 (another of mine), same kind of issue, and this ticket has
 been merged.
 I hope this one will do ;)

Ticket URL: <https://core.trac.wordpress.org/ticket/52076#comment:24>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform

More information about the wp-trac mailing list