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 0cdcd4cd85531..85f2c569e6dff 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
@@ -1610,7 +1610,30 @@ private function skip_script_data(): bool {
*/
$at += 6;
$c = $html[ $at ];
- if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) {
+ if (
+ /*
+ * These characters trigger state transitions of interest:
+ *
+ * - @see {https://html.spec.whatwg.org/multipage/parsing.html#script-data-end-tag-name-state}
+ * - @see {https://html.spec.whatwg.org/multipage/parsing.html#script-data-escaped-end-tag-name-state}
+ * - @see {https://html.spec.whatwg.org/multipage/parsing.html#script-data-double-escape-start-state}
+ * - @see {https://html.spec.whatwg.org/multipage/parsing.html#script-data-double-escape-end-state}
+ *
+ * The "\r" character is not present in the above references. However, "\r" must be
+ * treated the same as "\n". This is because the HTML Standard requires newline
+ * normalization during preprocessing which applies this replacement.
+ *
+ * - @see https://html.spec.whatwg.org/multipage/parsing.html#preprocessing-the-input-stream
+ * - @see https://infra.spec.whatwg.org/#normalize-newlines
+ */
+ '>' !== $c &&
+ ' ' !== $c &&
+ "\n" !== $c &&
+ '/' !== $c &&
+ "\t" !== $c &&
+ "\f" !== $c &&
+ "\r" !== $c
+ ) {
++$at;
continue;
}
diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php
index 511586f99327c..33979e50beb50 100644
--- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php
+++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php
@@ -2012,6 +2012,7 @@ public function test_script_tag_parsing( string $input, bool $closes ) {
public static function data_script_tag(): array {
return array(
'Basic script tag' => array( '', true ),
+ 'Basic script tag with close' => array( "", true ),
'Script with type attribute' => array( '', true ),
'Script data escaped' => array( '', true ),
'Script data double-escaped exit (comment)' => array( '', true ),
@@ -2021,6 +2022,7 @@ public static function data_script_tag(): array {
'Script tag with self-close flag (ignored)' => array( '', false ),
'Script data double-escaped' => array( '', false ),
+ 'Basic script tag double-escaped with ", false ),
);
}