From e1b9baa0218d3f5e7bb3f558de1cf1920c698bac Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Tue, 19 Aug 2025 12:20:24 -0500 Subject: [PATCH 1/5] Fix malformed ActivityPub handles for email-based logins Sanitize email-based usernames (e.g., from Site Kit Google login) to prevent malformed ActivityPub handles like @username@gmail.com@domain.com. - Modified get_preferred_username() to detect and sanitize email logins - Added comprehensive test coverage for email username sanitization - Ensures proper webfinger format without double @ symbols Fixes #2070. --- includes/model/class-user.php | 9 ++++- tests/includes/model/class-test-user.php | 46 ++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/includes/model/class-user.php b/includes/model/class-user.php index 0facb74d3..119db4d31 100644 --- a/includes/model/class-user.php +++ b/includes/model/class-user.php @@ -169,7 +169,14 @@ public function get_alternate_url() { * @return string The preferred username. */ public function get_preferred_username() { - return \get_the_author_meta( 'login', $this->_id ); + $login = \get_the_author_meta( 'login', $this->_id ); + + // Handle cases where login is an email address (e.g., from Site Kit Google login). + if ( str_contains( $login, '@' ) ) { + $login = \sanitize_title( $login ); + } + + return $login; } /** diff --git a/tests/includes/model/class-test-user.php b/tests/includes/model/class-test-user.php index a0d207176..d972d0bd0 100644 --- a/tests/includes/model/class-test-user.php +++ b/tests/includes/model/class-test-user.php @@ -128,4 +128,50 @@ public function test_get_moved_to() { $this->assertArrayHasKey( 'movedTo', $user ); $this->assertSame( 'https://example.com', $user['movedTo'] ); } + + /** + * Test that email-based usernames are properly sanitized for ActivityPub handles. + * + * @covers ::get_preferred_username + * @covers ::get_webfinger + */ + public function test_email_username_sanitization() { + // Test with email-based login (e.g., from Site Kit Google login). + $user_id = self::factory()->user->create( + array( + 'role' => 'author', + 'user_login' => 'testuser123@gmail.com', + ) + ); + $user = User::from_wp_user( $user_id ); + + // Preferred username should be sanitized. + $this->assertSame( 'testuser123-gmail-com', $user->get_preferred_username() ); + + // Webfinger should not have double @. + $expected_webfinger = 'testuser123-gmail-com@' . \wp_parse_url( \home_url(), \PHP_URL_HOST ); + $this->assertSame( $expected_webfinger, $user->get_webfinger() ); + + // Test another email format. + $user_id2 = self::factory()->user->create( + array( + 'role' => 'author', + 'user_login' => 'admin@googlemail.com', + ) + ); + $user2 = User::from_wp_user( $user_id2 ); + + $this->assertSame( 'admin-googlemail-com', $user2->get_preferred_username() ); + + // Test normal username (no email) remains unchanged. + $user_id3 = self::factory()->user->create( + array( + 'role' => 'author', + 'user_login' => 'normaluser', + ) + ); + $user3 = User::from_wp_user( $user_id3 ); + + $this->assertSame( 'normaluser', $user3->get_preferred_username() ); + } } From 477d97395dd14579afd5d386335bd59c11c4504a Mon Sep 17 00:00:00 2001 From: Automattic Bot Date: Tue, 19 Aug 2025 19:21:09 +0200 Subject: [PATCH 2/5] Add changelog --- .github/changelog/2082-from-description | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .github/changelog/2082-from-description diff --git a/.github/changelog/2082-from-description b/.github/changelog/2082-from-description new file mode 100644 index 000000000..b0adafae8 --- /dev/null +++ b/.github/changelog/2082-from-description @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +Fix malformed ActivityPub handles for users with email-based logins (e.g., from Site Kit Google authentication) From 5eeb2ed0e95a945cde9f19df4e58d0c67b9b3287 Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Tue, 19 Aug 2025 12:24:12 -0500 Subject: [PATCH 3/5] Add global namespace to str_contains in User model Prefixed str_contains with a backslash to ensure the global PHP function is used, preventing potential issues with overridden or namespaced functions. --- includes/model/class-user.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/model/class-user.php b/includes/model/class-user.php index 119db4d31..68e3db3b8 100644 --- a/includes/model/class-user.php +++ b/includes/model/class-user.php @@ -172,7 +172,7 @@ public function get_preferred_username() { $login = \get_the_author_meta( 'login', $this->_id ); // Handle cases where login is an email address (e.g., from Site Kit Google login). - if ( str_contains( $login, '@' ) ) { + if ( \str_contains( $login, '@' ) ) { $login = \sanitize_title( $login ); } From 1a3d79752900912dce064b53dc6f5b32f103f6b7 Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Tue, 19 Aug 2025 12:26:46 -0500 Subject: [PATCH 4/5] Fix code style alignment in test Fix PHPCS alignment warnings for variable assignments. --- tests/includes/model/class-test-user.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/includes/model/class-test-user.php b/tests/includes/model/class-test-user.php index d972d0bd0..32285c36b 100644 --- a/tests/includes/model/class-test-user.php +++ b/tests/includes/model/class-test-user.php @@ -143,7 +143,7 @@ public function test_email_username_sanitization() { 'user_login' => 'testuser123@gmail.com', ) ); - $user = User::from_wp_user( $user_id ); + $user = User::from_wp_user( $user_id ); // Preferred username should be sanitized. $this->assertSame( 'testuser123-gmail-com', $user->get_preferred_username() ); @@ -159,7 +159,7 @@ public function test_email_username_sanitization() { 'user_login' => 'admin@googlemail.com', ) ); - $user2 = User::from_wp_user( $user_id2 ); + $user2 = User::from_wp_user( $user_id2 ); $this->assertSame( 'admin-googlemail-com', $user2->get_preferred_username() ); @@ -170,7 +170,7 @@ public function test_email_username_sanitization() { 'user_login' => 'normaluser', ) ); - $user3 = User::from_wp_user( $user_id3 ); + $user3 = User::from_wp_user( $user_id3 ); $this->assertSame( 'normaluser', $user3->get_preferred_username() ); } From a49da59021249d38848cd043302e50943fa763a3 Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Wed, 20 Aug 2025 07:59:15 -0500 Subject: [PATCH 5/5] Fix email username sanitization logic Use explicit string replacement instead of sanitize_title() to ensure dots are converted to dashes as expected by tests. Also use filter_var() for proper email validation. --- includes/model/class-user.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/model/class-user.php b/includes/model/class-user.php index 68e3db3b8..e3eb39182 100644 --- a/includes/model/class-user.php +++ b/includes/model/class-user.php @@ -172,8 +172,8 @@ public function get_preferred_username() { $login = \get_the_author_meta( 'login', $this->_id ); // Handle cases where login is an email address (e.g., from Site Kit Google login). - if ( \str_contains( $login, '@' ) ) { - $login = \sanitize_title( $login ); + if ( \filter_var( $login, FILTER_VALIDATE_EMAIL ) ) { + $login = \str_replace( array( '@', '.' ), '-', $login ); } return $login;