Commit 570eedee14 for wordpress.org
commit 570eedee14daf9e040827c5f650586dffb7931ca
Author: jonsurrell <jonsurrell@git.wordpress.org>
Date: Mon Sep 7 08:46:52 2026 +0000
HTML API: Allow raw text which cannot close its own element.
Developed in: https://github.com/WordPress/wordpress-develop/pull/12914
Props khokansardar, jonsurrell, shailu25.
Fixes #65824.
Built from https://develop.svn.wordpress.org/trunk@63513
git-svn-id: http://core.svn.wordpress.org/trunk@62689 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-includes/html-api/class-wp-html-tag-processor.php b/wp-includes/html-api/class-wp-html-tag-processor.php
index bbfbbea59b..4e3063f5bd 100644
--- a/wp-includes/html-api/class-wp-html-tag-processor.php
+++ b/wp-includes/html-api/class-wp-html-tag-processor.php
@@ -4092,11 +4092,20 @@ class WP_HTML_Tag_Processor {
* Because of this, content which could potentially modify the SCRIPT tag’s
* HTML structure is rejected here. It’s the responsibility of calling code to
* perform whatever semantic escaping is necessary to avoid problematic strings.
+ *
+ * Both the start tag `<script` and the end tag `</script` are rejected. It’s
+ * easy to assume that only an end tag can alter the HTML structure, but a
+ * start tag which follows `<!--` moves the tokenizer into the double-escaped
+ * states, where a later `</script>` no longer closes the element.
+ *
+ * In both cases the tag name ends only at one of the characters matched
+ * below, so text such as `</scriptx>` cannot change that structure and is
+ * safe to set.
+ *
+ * @link https://html.spec.whatwg.org/#script-data-end-tag-name-state
+ * @link https://html.spec.whatwg.org/#script-data-double-escape-start-state
*/
- if (
- false !== stripos( $plaintext_content, '<script' ) ||
- false !== stripos( $plaintext_content, '</script' )
- ) {
+ if ( 1 === preg_match( '~</?script[ \t\f\r\n/>]~i', $plaintext_content ) ) {
_doing_it_wrong(
__METHOD__,
__( 'SCRIPT text with an unrecognized content type cannot contain a SCRIPT tag. Apply the escaping appropriate for the content type.' ),
@@ -4116,7 +4125,14 @@ class WP_HTML_Tag_Processor {
case 'NOFRAMES':
case 'XMP':
$tag_name = $this->get_tag();
- if ( false !== stripos( $plaintext_content, "</{$tag_name}" ) ) {
+
+ /*
+ * A tag name ends only at one of the characters matched below, so text
+ * such as `</xmp-tag>` cannot close the element and is safe to set.
+ *
+ * @link https://html.spec.whatwg.org/#rawtext-end-tag-name-state
+ */
+ if ( 1 === preg_match( '~</' . preg_quote( $tag_name, '~' ) . '[ \t\f\r\n/>]~i', $plaintext_content ) ) {
_doing_it_wrong(
__METHOD__,
sprintf(
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 8c94678239..920fde9cc6 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-alpha-63512';
+$wp_version = '7.2-alpha-63513';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.