Skip to content

Script Loader: Pass the printed text to the wp_inline_script_attributes filter - #14274

Closed
sirreal wants to merge 2 commits into
WordPress:trunkfrom
sirreal:fix/66308-inline-script-attributes-filter-text
Closed

sirreal wants to merge 2 commits into
WordPress:trunkfrom
sirreal:fix/66308-inline-script-attributes-filter-text

Conversation

@sirreal

@sirreal sirreal commented Oct 14, 2026

Copy link
Copy Markdown
Member

wp_get_inline_script_tag() passed $data to the wp_inline_script_attributes filter and then set it as the SCRIPT text. Since r61477, set_modifiable_text() escapes <script and </script in JavaScript and JSON, so the printed text can differ from what the filter received. A callback that derives an attribute from the text, such as a CSP hash, produces a value that does not match the element, and the browser blocks the script.

The filter now receives get_modifiable_text(): the text as a browser parses it from the printed tag, with <script and </script escaped and CR and CRLF normalized to LF.

The Tag Processor chooses the escaping from the type and language attributes when the text is set, so the tag is built from the caller's attributes first, the filter runs on that text, and when the filter changes the attributes the tag is built again from the filtered array. Two consequences:

  • The filter no longer runs when the caller's attributes make the data unembeddable. The function ran it and then returned '' before.
  • A callback that changes type or language between a recognized and an unrecognized content type changes the escaping of the printed text after the filter saw it. The filter docblock states this.

Tests cover the escaped text, newline normalization, attribute replacement, and both failure paths.

Trac ticket: https://core.trac.wordpress.org/ticket/66308

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Fable 5.1
Used for: Implementation, tests, review and description.


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.

…tes` filter.

`wp_get_inline_script_tag()` passed the raw data to the filter and then set the text with `WP_HTML_Tag_Processor::set_modifiable_text()`, which escapes `<script` and `</script` in JavaScript and JSON, so a callback deriving an attribute from the text, such as a CSP hash, could compute it from text that was not printed. The function now builds the tag from the caller's attributes first, passes the text as the browser parses it from the printed tag, and builds the tag again when the filter changes the attributes, because the `type` and `language` attributes decide how the text is escaped.

See #66308.
@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@sirreal

sirreal commented Oct 14, 2026

Copy link
Copy Markdown
Member Author

This is a tricky problem because the resulting script tag contents depend on the type (or language) attribute to apply escaping rules to the content.

If the filter is applied first, the filter function may be passed script data that isn't what's actually printed. But if the filter is applied after, then the attributes necessary for escaping may not have been applied so escaping may be applied incorrectly or not applied at all.

I don't think the same problem applies to #13250 because the content type of style tags is CSS.

@sirreal

sirreal commented Oct 14, 2026

Copy link
Copy Markdown
Member Author

This seems like a change in contract. Instead I think we should document the limitation and consider workarounds if it's essential that the filter see the exact contents that will be printed in the script tag.

@sirreal sirreal closed this Oct 14, 2026
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