From 612e80e5862f0a748b16647c1d7d2009676b0030 Mon Sep 17 00:00:00 2001 From: Sukhendu Sekhar Guria Date: Wed, 8 Apr 2026 16:19:08 +0530 Subject: [PATCH] comments: allow img tags when editing comments in admin. --- src/wp-includes/comment.php | 28 +++++++++++++ tests/phpunit/tests/comment.php | 72 +++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index 5395997ecd0ef..b0a643ed9058e 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -2635,6 +2635,30 @@ function wp_update_comment( $commentarr, $wp_error = false ) { $filter_comment = ! user_can( $comment['user_id'] ?? 0, 'unfiltered_html' ); } + // Allow images in comments when edited by users with appropriate capabilities in admin. + $img_filter_callback = null; + if ( is_admin() && current_user_can( 'edit_comment', $commentarr['comment_ID'] ) ) { + $img_filter_callback = function ( $allowed_html ) { + if ( ! isset( $allowed_html['img'] ) ) { + $allowed_html['img'] = array( + 'alt' => true, + 'align' => true, + 'border' => true, + 'height' => true, + 'hspace' => true, + 'loading' => true, + 'longdesc' => true, + 'vspace' => true, + 'src' => true, + 'usemap' => true, + 'width' => true, + ); + } + return $allowed_html; + }; + add_filter( 'wp_kses_allowed_html', $img_filter_callback ); + } + if ( $filter_comment ) { add_filter( 'pre_comment_content', 'wp_filter_kses' ); } @@ -2653,6 +2677,10 @@ function wp_update_comment( $commentarr, $wp_error = false ) { remove_filter( 'pre_comment_content', 'wp_filter_kses' ); } + if ( $img_filter_callback ) { + remove_filter( 'wp_kses_allowed_html', $img_filter_callback ); + } + // Now extract the merged array. $data = wp_unslash( $commentarr ); diff --git a/tests/phpunit/tests/comment.php b/tests/phpunit/tests/comment.php index 11e78140f1020..923abf97179e3 100644 --- a/tests/phpunit/tests/comment.php +++ b/tests/phpunit/tests/comment.php @@ -176,6 +176,78 @@ public function test_update_comment_from_unprivileged_user_by_privileged_user() ); } + /** + * @ticket 57979 + * + * @covers ::wp_update_comment + */ + public function test_update_comment_allows_images_in_admin_by_privileged_user() { + wp_set_current_user( self::$user_id ); + + $comment_id = wp_new_comment( + array( + 'comment_post_ID' => self::$post_id, + 'comment_author' => 'Author', + 'comment_author_url' => 'http://example.localhost/', + 'comment_author_email' => 'author@example.com', + 'user_id' => self::$user_id, + 'comment_content' => 'click', + ) + ); + + wp_set_current_user( 0 ); + + $admin_id = self::factory()->user->create( + array( + 'role' => 'administrator', + 'user_login' => 'test_wp_admin_get', + 'user_pass' => 'password', + 'user_email' => 'testadmin@example.com', + ) + ); + + wp_set_current_user( $admin_id ); + + // Simulate admin context. + set_current_screen( 'edit-comments' ); + + wp_update_comment( + array( + 'comment_ID' => $comment_id, + 'comment_content' => 'Test image', + ) + ); + + // Reset current screen. + set_current_screen( 'front' ); + + wp_set_current_user( 0 ); + + $comment = get_comment( $comment_id ); + $this->assertStringContainsString( 'comment_content ); + $this->assertStringContainsString( 'src="http://example.localhost/image.jpg"', $comment->comment_content ); + $this->assertStringContainsString( 'alt="Test image"', $comment->comment_content ); + + // Verify that malicious attributes are still stripped by KSES. + wp_set_current_user( $admin_id ); + set_current_screen( 'edit-comments' ); + + wp_update_comment( + array( + 'comment_ID' => $comment_id, + 'comment_content' => '', + ) + ); + + set_current_screen( 'front' ); + wp_set_current_user( 0 ); + + $comment = get_comment( $comment_id ); + $this->assertStringContainsString( 'comment_content ); + $this->assertStringNotContainsString( 'onerror', $comment->comment_content ); + $this->assertStringNotContainsString( 'alert', $comment->comment_content ); + } + /** * @ticket 30627 *