-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Ensure block editor preloading middleware JSON is correctly escaped #8145
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
Ensure block editor preloading middleware JSON is correctly escaped #8145
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Test using WordPress PlaygroundThe 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
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
4089bdc to
7defd55
Compare
|
I plan to add tests to this using |
|
I'm concerned this pattern is very common. I wonder if there should be some dedicated functions. Here are some examples of this exact pattern in the site editor that are susceptible to the same problem: wordpress-develop/src/wp-admin/site-editor.php Lines 254 to 292 in f83e663
|
What’s your concern? that it will contain |
That's the problem here that may produce a broken page. I'm unaware of others, but |
858012e to
83f2c7e
Compare
|
I've pushed a test leveraging new The failure appears as |
|
Example failures on CI can be observed here: (I'm updating the test name after the CI run, but the result is the same). |
Could we perhaps create a new Issue or document where we can start enumerating the situations in which this can go bad? perhaps a new test suite with no new code, in a PR. I find that it’s hard for me to grasp unless it’s a particularly good day and I have my full concentration. There are differences, aren’t there, between printing these three situations? <script type="application/json">
{ "some": "json" }
</script><script>
const data = { "some": "json" };
</script><script>
callMeMaybe( { "some": "json" } );
</script>I thought these were distinct cases with different edges but I can’t remember how. |
4322bb0 to
85bccee
Compare
Will you describe the goal of that? Is this to find some a more general fix or explore alternatives?
I don't think there are differences today. I did a deep dive and there used to be a difference. It's the JavaScript is a superset of JSON proposal that was addressed in es2019. Platform support seems ubiquitous. Note that this is only relevant when using More details and demoIn short, there were situations where serializing JSON (to read as JSON) and serializing JSON (inside of a JavaScript context) needed to be treated slightly differently. In browsers without es2019 JavaScript is a superset of JSON support (I tried Chrome 65, the latest Chrome without support) and if there are strings with This demo shows the differences (only in older browsers, e.g. Chrome <= 65). This code will error with SyntaxError: Invalid or unexpected token because of the unescaped <body>
<script defer>
const x = <?php echo json_encode(
[ 'test' => "x\u{2028}\u{2029}y\n" ],
JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS
); ?>;
document.body.textContent = [...x.test].map(c => c.toString(16) ).join('');
</script>This, however, is fine because the characters are not evaluated as JavaScript. They're read as JSON text, where they've always been allowed: <body>
<script type="application/json" id="x">
<?php echo json_encode(
[ 'test' => "x\u{2028}\u{2029}y\n" ],
JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS
); ?>
</script>
<script defer>
const x = JSON.parse( document.getElementById( 'x' ).textContent );
document.body.textContent = [...x.test].map(c => c.toString(16) ).join('');
</script>Again, in today's JavaScript all of these cases are fine. And this only applies when certain JSON flags are applied that are not used here. In all the situations you list we need have the same requirements of the JSON:
I believe the From the JavaScript/JSON perspective, the emitted JSON should be valid, the question of line terminators is not a concern today and the relevant flags are not proposed in this PR. |
|
This is really helpful, @sirreal — thank you for verifying with the older browser. |
|
There's one additional wrinkle I considered: XHTML. None of the XHTML-related behavior changes in this PR. XHTML is likely not used today and it would be good to remove support (https://core.trac.wordpress.org/ticket/59883). The good news is that themes that don't declare HTML5 script support (potentially "supporting XHTML") should work correctly with the encoding as proposed thanks to the CDATA wrappers used. Also note that this does not change with this PR as the escaping of Invalid XHTML ( <?php header('Content-Type: application/xhtml+xml; charset=UTF-8'); ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<body>
<script>
alert('Invalid: <>&');
</script>
</body>
</html>The following would be valid with the <script>
alert('escaped: \x3C>\x26');
</script>WordPress will wrap inline script tag contents with CDATA if HTML5 support is not declared. That looks like this (with the proposed <script>
/* <![CDATA[ */
alert('CDATA escaped: \u003C\u003E&');
/* ]]> */
</script> |
|
I'd like to move ahead with this PR, I believe it's the correct behavior and this same change should apply to many other places where data is JSON encoded for use in script tags throughout Core. |
This test provides an example where certain HTML embedded inside of JSON may break the script tag from closing.
The test for removing redundant leading slashes is likely redundant itself. It checks that something that does not require escaping is not escaped.
This test is correctly checking that a leading forward "/" slash is prepended to rest routes.
These flags should be safe to use in all contexts.
This reverts commit d630c7d5610ab5ba91e0c304776add3d8daf40ec.
This reverts commit 97edc8bf6a09d526cd715ce6e7c54fdbc8001e59.
This reverts commit 8d2761a.
This reverts commit 6946702.
85bccee to
1b41f43
Compare
dmsnell
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates and extra verification @sirreal.
Adds the appropriate JSON flags to `wp_json_encode()` to safely encode data for use in script tags. Developed in #8145. Props jonsurrell, bernhard-reiter, dmsnell, artpi, ankitkumarshah, abcd95, dilipbheda, sainathpoojary, shanemuir. Fixes #62797. git-svn-id: https://develop.svn.wordpress.org/trunk@60648 602fd350-edb4-49c9-b593-d223f7449a82
Adds the appropriate JSON flags to `wp_json_encode()` to safely encode data for use in script tags. Developed in WordPress/wordpress-develop#8145. Props jonsurrell, bernhard-reiter, dmsnell, artpi, ankitkumarshah, abcd95, dilipbheda, sainathpoojary, shanemuir. Fixes #62797. Built from https://develop.svn.wordpress.org/trunk@60648 git-svn-id: http://core.svn.wordpress.org/trunk@59984 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Adds the appropriate JSON flags to `wp_json_encode()` to safely encode data for use in script tags. Developed in WordPress/wordpress-develop#8145. Props jonsurrell, bernhard-reiter, dmsnell, artpi, ankitkumarshah, abcd95, dilipbheda, sainathpoojary, shanemuir. Fixes #62797. Built from https://develop.svn.wordpress.org/trunk@60648 git-svn-id: https://core.svn.wordpress.org/trunk@59984 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Adds the appropriate JSON flags to `wp_json_encode()` to safely encode data for use in script tags. Developed in WordPress#8145. Props jonsurrell, bernhard-reiter, dmsnell, artpi, ankitkumarshah, abcd95, dilipbheda, sainathpoojary, shanemuir. Fixes #62797. git-svn-id: https://develop.svn.wordpress.org/trunk@60648 602fd350-edb4-49c9-b593-d223f7449a82
Adds the appropriate JSON flags to `wp_json_encode()` to safely encode data for use in script tags. Developed in WordPress#8145. Props jonsurrell, bernhard-reiter, dmsnell, artpi, ankitkumarshah, abcd95, dilipbheda, sainathpoojary, shanemuir. Fixes #62797. git-svn-id: https://develop.svn.wordpress.org/trunk@60648 602fd350-edb4-49c9-b593-d223f7449a82
Fixes #62797 by correctly escaping JSON included inside JavaScript in a
scripttag.wp_add_inline_scriptwill correctly escape closing script tags</script>which prevents script contents from breaking out of the script, it does not handle cases where some content may enter the HTML script data double escaped state and prevent the real script closing tag from closing the script tag as expected, leading to a broken document where the script tag remains open.This can be tested by applying the patch and following the reproduction steps in #62797.
Trac ticket: https://core.trac.wordpress.org/ticket/62797
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.