Make WordPress Core

Opened 3 months ago

Last modified 3 months ago

#60693 new defect (bug)

"Previously approved comment" for logged out users bug

Reported by: jmorti's profile jmorti Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 6.4.3
Component: Comments Keywords: 2nd-opinion
Focuses: Cc:

Description

When "Comment author must have a previously approved comment" is checked in the discussion settings, comments made by registered users who are logged out, go to moderation every time. The check comment function looks for previous comments under their user id but if they have only commented while logged out, no id is recorded. This bug has caused our users and our team major frustration. Can someone please address? Thanks!

Change History (7)

#1 @jmorti
3 months ago

Here's the problem code in comment.php:

<?php
        /*
         * Check if the option to approve comments by previously-approved authors is enabled.
         *
         * If it is enabled, check whether the comment author has a previously-approved comment,
         * as well as whether there are any moderation keywords (if set) present in the author
         * email address. If both checks pass, return true. Otherwise, return false.
         */
        if ( 1 == get_option( 'comment_previously_approved' ) ) {
                if ( 'trackback' !== $comment_type && 'pingback' !== $comment_type && '' !== $author && '' !== $email ) {
                        $comment_user = get_user_by( 'email', wp_unslash( $email ) );
                        if ( ! empty( $comment_user->ID ) ) {
                                $ok_to_comment = $wpdb->get_var( $wpdb->prepare( "SELECT comment_approved FROM $wpdb->comments WHERE user_id = %d AND comment_approved = '1' LIMIT 1", $comment_user->ID ) );//<--doesnt work when registered users are logged out and comment
                        } else {
                                // expected_slashed ($author, $email)
                                $ok_to_comment = $wpdb->get_var( $wpdb->prepare( "SELECT comment_approved FROM $wpdb->comments WHERE comment_author = %s AND comment_author_email = %s and comment_approved = '1' LIMIT 1", $author, $email ) );
                        }
                        if ( ( 1 == $ok_to_comment ) &&
                                ( empty( $mod_keys ) || ! str_contains( $email, $mod_keys ) ) ) {
                                        return true;
                        } else {
                                return false;
                        }
                } else {
                        return false;
                }
        }
        return true;
}

#2 @knutsp
3 months ago

  • Keywords 2nd-opinion added

This is the way it has always worked, and I see this as a feature, not a bug. But annoying.

If the comment being made is from an email belonging to a registered user, the search for earlier, approved comments is made by that found and assumed user-ID, not by the email.

If WP was to search for comments by email regardless of successfully looking it up as a registered user, it will be too easy (for spammers) to impersonate that user to avoid moderation. While the emails of visiting commenters are not public, the emails of registered users may be listed publicly, or at least somewhat guessable on some sites.

A change to forcing registered user to log in before commenting, based on the given email, would also not be safe enough, is this may definitely confirm a specific email belongs to a registered user.

My workaroud is to advice registered users to keep their browsing local device (computer) account (User Agent) secure and self locking and to stay logged in on normal web apps like WP sites, or always simply log in before commenting on WP.

Some users have learned to log out of any system after a session, at least on desktops, but tend to trust the device security when using native mobile apps. Immediately logging out is either forced, or at least fine, for high risk or sensitive data systems, or when among people one should not trust. For most uses, staying logged in for two weeks (remember me), and using multi factor authentication, is the best compromise between security and usability, IMHO.

#3 @jmorti
3 months ago

Nice thoughts but it's still a bug because it sends all the registered but logged out user's comments to moderation and when you get hundreds of comments per day, that's a real problem.

Last edited 3 months ago by jmorti (previous) (diff)

#4 @swissspidy
3 months ago

Anyone can impersonate the registered user simply by using their email address. Just passing those comments through wouldn't be good. Plugins like https://wordpress.org/plugins/impostercide/ can force people to log in if they use such an email. I think that would work well for your use case, so I'd recommend using a plugin.

Related / possible duplicate of: #10931

#5 @jmorti
3 months ago

Making people login defeats the purpose of the "previously approved comment" feature.

Last edited 3 months ago by jmorti (previous) (diff)

#6 @jmorti
3 months ago

Wouldn't it make more sense to check if the user is logged in? Maybe something like this:

<?php
        /*
         * Check if the option to approve comments by previously-approved authors is enabled.
         *
         * If it is enabled, check whether the comment author has a previously-approved comment,
         * as well as whether there are any moderation keywords (if set) present in the author
         * email address. If both checks pass, return true. Otherwise, return false.
         */
        if ( 1 == get_option( 'comment_previously_approved' ) ) {
                if ( 'trackback' !== $comment_type && 'pingback' !== $comment_type && '' !== $author && '' !== $email ) {
                        if ( is_user_logged_in() ) {
                                $comment_user = get_user_by( 'email', wp_unslash( $email ) );
                                $ok_to_comment = $wpdb->get_var( $wpdb->prepare( "SELECT comment_approved FROM $wpdb->comments WHERE user_id = %d AND comment_approved = '1' LIMIT 1", $comment_user->ID ) );//<--doesnt work when registered users are logged out and comment
                        } else {
                                // expected_slashed ($author, $email)
                                $ok_to_comment = $wpdb->get_var( $wpdb->prepare( "SELECT comment_approved FROM $wpdb->comments WHERE comment_author = %s AND comment_author_email = %s and comment_approved = '1' LIMIT 1", $author, $email ) );
                        }
                        if ( ( 1 == $ok_to_comment ) &&
                                ( empty( $mod_keys ) || ! str_contains( $email, $mod_keys ) ) ) {
                                        return true;
                        } else {
                                return false;
                        }
                } else {
                        return false;
                }
        }
        return true;
}
Last edited 3 months ago by jmorti (previous) (diff)

#7 @jmorti
3 months ago

@swissspidy - the plugin you suggested has been closed since 2022...

Note: See TracTickets for help on using tickets.