diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index 20303dc1e7e17..5a5273f4d627b 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -3853,6 +3853,26 @@ function wp_handle_comment_submission( $comment_data ) { } } + /* + * A logged-out visitor may not comment using the email address of a + * registered user. Requiring them to log in first prevents anyone from + * impersonating that user. This is checked whenever an email is provided, + * regardless of the 'require_name_email' option. See #10931. + */ + if ( ! $user->exists() && is_email( $comment_author_email ) && email_exists( $comment_author_email ) ) { + $login_url = wp_login_url( get_permalink( $comment_post_id ) ); + + return new WP_Error( + 'comment_author_must_login', + sprintf( + /* translators: %s: Login URL. */ + __( 'Error: That email address belongs to a registered user. Please log in to comment.' ), + esc_url( $login_url ) + ), + 403 + ); + } + $commentdata = array( 'comment_post_ID' => $comment_post_id, ); diff --git a/tests/phpunit/tests/comment/wpHandleCommentSubmission.php b/tests/phpunit/tests/comment/wpHandleCommentSubmission.php index 3f2ba84194a0d..832397b96de11 100644 --- a/tests/phpunit/tests/comment/wpHandleCommentSubmission.php +++ b/tests/phpunit/tests/comment/wpHandleCommentSubmission.php @@ -596,6 +596,71 @@ public function test_submitting_comment_with_invalid_email_when_name_email_requi $this->assertSame( $error, $comment->get_error_code() ); } + /** + * A logged-out visitor must not be able to comment using the email address + * of a registered user, to prevent impersonation. + * + * @ticket 10931 + */ + public function test_submitting_comment_anonymously_with_registered_email_returns_error() { + + $registered_email = get_userdata( self::$author_id )->user_email; + + $data = array( + 'comment_post_ID' => self::$post->ID, + 'comment' => 'Comment', + 'author' => 'Impersonator', + 'email' => $registered_email, + ); + $comment = wp_handle_comment_submission( $data ); + + $this->assertWPError( $comment ); + $this->assertSame( 'comment_author_must_login', $comment->get_error_code() ); + $this->assertSame( 403, $comment->get_error_data() ); + } + + /** + * A logged-out visitor may still comment with an email that is not tied to + * a registered user. + * + * @ticket 10931 + */ + public function test_submitting_comment_anonymously_with_unregistered_email_succeeds() { + + $data = array( + 'comment_post_ID' => self::$post->ID, + 'comment' => 'Comment', + 'author' => 'Comment Author', + 'email' => 'not-a-registered-user@example.org', + ); + $comment = wp_handle_comment_submission( $data ); + + $this->assertNotWPError( $comment ); + $this->assertInstanceOf( 'WP_Comment', $comment ); + $this->assertSame( 'not-a-registered-user@example.org', $comment->comment_author_email ); + } + + /** + * The registered-email check only targets logged-out visitors; a logged-in + * user commenting under their own (registered) email must still succeed. + * + * @ticket 10931 + */ + public function test_submitting_comment_as_logged_in_user_with_registered_email_succeeds() { + + wp_set_current_user( self::$author_id ); + + $data = array( + 'comment_post_ID' => self::$post->ID, + 'comment' => 'Comment', + ); + $comment = wp_handle_comment_submission( $data ); + + $this->assertNotWPError( $comment ); + $this->assertInstanceOf( 'WP_Comment', $comment ); + $this->assertSame( self::$author_id, (int) $comment->user_id ); + } + public function test_submitting_comment_with_no_comment_content_returns_error() { $error = 'require_valid_comment';