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';