Skip to content
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

Escape bootstrapScriptContent for javascript embedding into HTML #24385

Merged
merged 5 commits into from Apr 16, 2022

Conversation

gnoff
Copy link
Collaborator

@gnoff gnoff commented Apr 15, 2022

The previous escape was for Text into HTML and breaks script contents. The new escaping ensures that the script contents cannot prematurely close the host script tag by escaping script open and close string sequences using a unicode escape substitution.

closes: #23063

@sizebot
Copy link

sizebot commented Apr 15, 2022

Comparing: 726ba80...b8e4253

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.min.js = 131.43 kB 131.43 kB = 42.06 kB 42.05 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 136.70 kB 136.70 kB = 43.64 kB 43.64 kB
facebook-www/ReactDOM-prod.classic.js = 435.12 kB 435.12 kB = 79.88 kB 79.88 kB
facebook-www/ReactDOM-prod.modern.js = 420.12 kB 420.12 kB = 77.51 kB 77.51 kB
facebook-www/ReactDOMForked-prod.classic.js = 435.12 kB 435.12 kB = 79.88 kB 79.88 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable-semver/react-dom/umd/react-dom-server.browser.production.min.js +0.32% 33.65 kB 33.76 kB +0.50% 11.57 kB 11.62 kB
oss-stable/react-dom/umd/react-dom-server.browser.production.min.js +0.32% 33.65 kB 33.76 kB +0.50% 11.57 kB 11.62 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.production.min.js +0.32% 33.52 kB 33.63 kB +0.52% 11.44 kB 11.50 kB
oss-stable/react-dom/cjs/react-dom-server.browser.production.min.js +0.32% 33.52 kB 33.63 kB +0.52% 11.44 kB 11.50 kB
oss-experimental/react-dom/umd/react-dom-server.browser.production.min.js +0.31% 34.05 kB 34.16 kB +0.53% 11.70 kB 11.76 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.production.min.js +0.31% 33.92 kB 34.03 kB +0.49% 11.58 kB 11.63 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.production.min.js +0.29% 36.79 kB 36.90 kB +0.42% 12.49 kB 12.54 kB
oss-stable/react-dom/cjs/react-dom-server.node.production.min.js +0.29% 36.79 kB 36.90 kB +0.42% 12.49 kB 12.54 kB
oss-experimental/react-dom/cjs/react-dom-server.node.production.min.js +0.28% 37.25 kB 37.35 kB +0.43% 12.66 kB 12.71 kB
facebook-www/ReactDOMServerStreaming-prod.modern.js +0.24% 77.43 kB 77.61 kB +0.55% 16.42 kB 16.51 kB

Generated by 🚫 dangerJS against b8e4253

@gnoff gnoff requested a review from sebmarkbage April 15, 2022 18:41
Copy link
Collaborator

@sebmarkbage sebmarkbage left a comment

Choose a reason for hiding this comment

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

Some nits but the essence looks good.

packages/react-dom/src/server/escapeScriptForBrowser.js Outdated Show resolved Hide resolved

const scriptRegex = /(<\/|<)(s)(cript)/gi;
const scriptReplacer = (match, prefix, s, suffix) =>
`${prefix}${substitutions[s]}${suffix}`;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's make this an inline condition instead of going through a whole hidden class check and fake-map look up.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I meant s === 's' ? '\\u0073' : '\\u0053'

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

👍

The previous escape was for Text into HTML and breaks script contents. The new escaping ensures that the script contents cannot prematurely close the host script tag by escaping script open and close string sequences using a unicode escape substitution.
the escaping of this function does is tailored to the specific use case of how bootstrapScriptContent is currently set up and having it be a module suggests it is meant for a more general than it has been considered for.

Additionally the tests were redone to focus on practical implications for what is and is not escaped
@gnoff gnoff merged commit d40dc73 into facebook:main Apr 16, 2022
@gnoff gnoff deleted the fizz-escape-script branch April 16, 2022 17:47
const scriptReplacer = (match, prefix, s, suffix) =>
`${prefix}${s === 's' ? '\\u0073' : '\\u0053'}${suffix}`;

function escapeBootstrapScriptContent(scriptText) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe a leave a comment with the rationale and clarifying that this only works if the whole content is encoded and if it's an actual JS script tag, and doesn't work for attributes or CSS.

Copy link
Collaborator

@sebmarkbage sebmarkbage left a comment

Choose a reason for hiding this comment

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

lgtm

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

Successfully merging this pull request may close these issues.

React 18: bootstrapScriptContent escapes HTML so quotes can’t be used
4 participants