diff --git a/src/wp-includes/html-api/class-wp-html-tag-processor.php b/src/wp-includes/html-api/class-wp-html-tag-processor.php
index 169fabe750..1b4db41bce 100644
--- a/src/wp-includes/html-api/class-wp-html-tag-processor.php
+++ b/src/wp-includes/html-api/class-wp-html-tag-processor.php
@@ -1762,7 +1762,8 @@ class WP_HTML_Tag_Processor {
'T' === $html[ $this->token_starts_at + 6 ] &&
'A' === $html[ $this->token_starts_at + 7 ] &&
'[' === $html[ $this->token_starts_at + 8 ] &&
- ']' === $html[ $closer_at - 1 ]
+ ']' === $html[ $closer_at - 1 ] &&
+ ']' === $html[ $closer_at - 2 ]
) {
$this->parser_state = self::STATE_COMMENT;
$this->comment_type = self::COMMENT_AS_CDATA_LOOKALIKE;
diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor-token-scanning.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor-token-scanning.php
index 5381449105..295063a04c 100644
--- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor-token-scanning.php
+++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor-token-scanning.php
@@ -347,6 +347,38 @@ HTML
);
}
+ /**
+ * Ensures that normative CDATA sections are properly parsed.
+ *
+ * @ticket 60406
+ *
+ * @since 6.5.0
+ *
+ * @covers WP_HTML_Tag_Processor::next_token
+ */
+ public function test_cdata_comment_with_incorrect_closer() {
+ $processor = new WP_HTML_Tag_Processor( '' );
+ $processor->next_token();
+
+ $this->assertSame(
+ '#comment',
+ $processor->get_token_name(),
+ "Should have found comment token but found {$processor->get_token_name()} instead."
+ );
+
+ $this->assertSame(
+ WP_HTML_Processor::COMMENT_AS_INVALID_HTML,
+ $processor->get_comment_type(),
+ 'Should have detected invalid HTML comment.'
+ );
+
+ $this->assertSame(
+ '[CDATA[this is missing a closing square bracket]',
+ $processor->get_modifiable_text(),
+ 'Found incorrect modifiable text.'
+ );
+ }
+
/**
* Ensures that abruptly-closed CDATA sections are properly parsed as comments.
*
@@ -366,6 +398,12 @@ HTML
"Should have found a bogus comment but found {$processor->get_token_name()} instead."
);
+ $this->assertSame(
+ WP_HTML_Processor::COMMENT_AS_INVALID_HTML,
+ $processor->get_comment_type(),
+ 'Should have detected invalid HTML comment.'
+ );
+
$this->assertNull(
$processor->get_tag(),
'Should not have been able to query tag name on non-element token.'