Skip to content

Fix inline script tag escaping #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 18 commits into
base: trunk
Choose a base branch
from

Conversation

sirreal
Copy link
Owner

@sirreal sirreal commented Jul 23, 2025

To do:

  • Match at the end of the string, something like /<\/script$/i

Trac ticket:


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

@sirreal sirreal force-pushed the fix/62797-inline-script-tag-escape-alternate branch from 96f20ba to 3052284 Compare July 24, 2025 11:29
@sirreal sirreal force-pushed the fix/62797-inline-script-tag-escape-alternate branch from 3052284 to 4b9aa42 Compare July 30, 2025 08:03
@sirreal sirreal requested a review from Copilot July 30, 2025 16:54
Copilot

This comment was marked as outdated.

@sirreal sirreal requested a review from Copilot July 30, 2025 19:32
Copilot

This comment was marked as outdated.

sirreal added 2 commits July 30, 2025 22:11
These tricky sequences do terminate a tag name because they
are handled when normalizing newlines in pre-processing
(before tokenization).
@sirreal sirreal requested a review from Copilot July 30, 2025 21:23
Copilot

This comment was marked as outdated.

@sirreal sirreal requested a review from Copilot August 6, 2025 11:11
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request fixes inline script tag escaping to prevent script injection vulnerabilities when embedding data in HTML script tags. The changes improve security by properly escaping dangerous patterns that could break out of script contexts.

  • Implements proper escaping for script tag content that could close or interfere with script elements
  • Adds comprehensive detection of JavaScript vs non-JavaScript script tags based on HTML specification
  • Updates inline script functions to use the new HTML Tag Processor for safe content handling

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/wp-includes/html-api/class-wp-html-tag-processor.php Adds JavaScript script tag detection and Unicode escaping for dangerous patterns
src/wp-includes/script-loader.php Updates inline script generation to use HTML Tag Processor for safe escaping
src/wp-includes/functions.wp-scripts.php Improves script tag detection and content extraction using HTML Tag Processor
src/wp-includes/block-editor.php Adds JSON_UNESCAPED_SLASHES flag to prevent double-escaping of slashes
tests/phpunit/tests/html-api/wpHtmlTagProcessorModifiableText.php Adds comprehensive test coverage for script tag escaping scenarios
tests/phpunit/tests/blocks/editor.php Updates test expectations and adds security test for script tag closure

*
* @see https://html.spec.whatwg.org/multipage/scripting.html#prepare-the-script-element
*
* @since {WP_VERSION}
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @SInCE tag contains a placeholder '{WP_VERSION}' instead of an actual version number. This should be replaced with the specific WordPress version when this feature is released.

Suggested change
* @since {WP_VERSION}
* @since 6.5.0

Copilot uses AI. Check for mistakes.

* JavaScript can be safely escaped.
* Non-JavaScript script tags have unknown semantics.
*
* @todo consider applying to JSON and importmap script tags as well.
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This TODO comment suggests unfinished work. Consider either implementing the suggested feature for JSON and importmap script tags or removing this comment if it's not planned for this release.

Suggested change
* @todo consider applying to JSON and importmap script tags as well.

Copilot uses AI. Check for mistakes.

'Tricky script open tag with \r' => array( '<script></script>', "<!-- <script\r>", "<script><!-- <\\u0073cript\r></script>" ),
'Tricky script open tag with \r\n' => array( '<script></script>', "<!-- <script\r\n>", "<script><!-- <\\u0073cript\r\n></script>" ),
'Tricky script close tag with \r' => array( '<script></script>', "// </script\r>", "<script>// </\\u0073cript\r></script>" ),
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\\u0073cript\r\n></script>" ),
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expected output contains double backslashes '\u0073' which appears incorrect. It should be '\u0073' (single backslash) to represent the Unicode escape sequence properly.

Suggested change
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\\u0073cript\r\n></script>" ),
'Tricky script open tag with \r' => array( '<script></script>', "<!-- <script\r>", "<script><!-- <\u0073cript\r></script>" ),
'Tricky script open tag with \r\n' => array( '<script></script>', "<!-- <script\r\n>", "<script><!-- <\u0073cript\r\n></script>" ),
'Tricky script close tag with \r' => array( '<script></script>', "// </script\r>", "<script>// </\u0073cript\r></script>" ),
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\u0073cript\r\n></script>" ),

Copilot uses AI. Check for mistakes.

'Tricky script open tag with \r' => array( '<script></script>', "<!-- <script\r>", "<script><!-- <\\u0073cript\r></script>" ),
'Tricky script open tag with \r\n' => array( '<script></script>', "<!-- <script\r\n>", "<script><!-- <\\u0073cript\r\n></script>" ),
'Tricky script close tag with \r' => array( '<script></script>', "// </script\r>", "<script>// </\\u0073cript\r></script>" ),
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\\u0073cript\r\n></script>" ),
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expected output contains double backslashes '\u0073' which appears incorrect. It should be '\u0073' (single backslash) to represent the Unicode escape sequence properly.

Suggested change
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\\u0073cript\r\n></script>" ),
'Tricky script open tag with \r' => array( '<script></script>', "<!-- <script\r>", "<script><!-- <\u0073cript\r></script>" ),
'Tricky script open tag with \r\n' => array( '<script></script>', "<!-- <script\r\n>", "<script><!-- <\u0073cript\r\n></script>" ),
'Tricky script close tag with \r' => array( '<script></script>', "// </script\r>", "<script>// </\u0073cript\r></script>" ),
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\u0073cript\r\n></script>" ),

Copilot uses AI. Check for mistakes.

'Tricky script open tag with \r' => array( '<script></script>', "<!-- <script\r>", "<script><!-- <\\u0073cript\r></script>" ),
'Tricky script open tag with \r\n' => array( '<script></script>', "<!-- <script\r\n>", "<script><!-- <\\u0073cript\r\n></script>" ),
'Tricky script close tag with \r' => array( '<script></script>', "// </script\r>", "<script>// </\\u0073cript\r></script>" ),
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\\u0073cript\r\n></script>" ),
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expected output contains double backslashes '\u0073' which appears incorrect. It should be '\u0073' (single backslash) to represent the Unicode escape sequence properly.

Suggested change
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\\u0073cript\r\n></script>" ),
'Tricky script open tag with \r' => array( '<script></script>', "<!-- <script\r>", "<script><!-- <\u0073cript\r></script>" ),
'Tricky script open tag with \r\n' => array( '<script></script>', "<!-- <script\r\n>", "<script><!-- <\u0073cript\r\n></script>" ),
'Tricky script close tag with \r' => array( '<script></script>', "// </script\r>", "<script>// </\u0073cript\r></script>" ),
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\u0073cript\r\n></script>" ),

Copilot uses AI. Check for mistakes.

'Tricky script open tag with \r' => array( '<script></script>', "<!-- <script\r>", "<script><!-- <\\u0073cript\r></script>" ),
'Tricky script open tag with \r\n' => array( '<script></script>', "<!-- <script\r\n>", "<script><!-- <\\u0073cript\r\n></script>" ),
'Tricky script close tag with \r' => array( '<script></script>', "// </script\r>", "<script>// </\\u0073cript\r></script>" ),
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\\u0073cript\r\n></script>" ),
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expected output contains double backslashes '\u0073' which appears incorrect. It should be '\u0073' (single backslash) to represent the Unicode escape sequence properly.

Suggested change
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\\u0073cript\r\n></script>" ),
'Tricky script open tag with \r' => array( '<script></script>', "<!-- <script\r>", "<script><!-- <\u0073cript\r></script>" ),
'Tricky script open tag with \r\n' => array( '<script></script>', "<!-- <script\r\n>", "<script><!-- <\u0073cript\r\n></script>" ),
'Tricky script close tag with \r' => array( '<script></script>', "// </script\r>", "<script>// </\u0073cript\r></script>" ),
'Tricky script close tag with \r\n' => array( '<script></script>', "// </script\r\n>", "<script>// </\u0073cript\r\n></script>" ),

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant