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

Fix an XSS in Server Islands. #11508

Merged
merged 4 commits into from
Jul 19, 2024

Conversation

cramforce
Copy link
Contributor

Discussed with @FredKSchott that this is OK to disclose since Server Islands are still experimental.

It's generally not safe to use JSON.stringify to interpolate potentially attacker controlled data into <script> tags as JSON doesn't escape <>"' and so one can use it to break out of the script tag and e.g. make a new one with controlled content.

See https://pragmaticwebsecurity.com/articles/spasecurity/json-stringify-xss

Changes

No behavior change expected. All tests should still pass unless they trigger the encoding change.

Testing

Not at all. I couldn't get tests to run.

Discussed with @FredKSchott that this is OK to disclose since Server Islands are still experimental.

It's generally not safe to use `JSON.stringify` to interpolate potentially attacker controlled data into `<script>` tags as JSON doesn't escape `<>"'` and so one can use it to break out of the script tag and e.g. make a new one with controlled content.

See https://pragmaticwebsecurity.com/articles/spasecurity/json-stringify-xss
Copy link

changeset-bot bot commented Jul 19, 2024

🦋 Changeset detected

Latest commit: 81612ed

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added the pkg: astro Related to the core `astro` package (scope) label Jul 19, 2024
@matthewp
Copy link
Contributor

Wonderful, thank you very much.

@ascorbic
Copy link
Contributor

Thansk! Unfortunately this doesn't work, because it escapes the quotes too, leading to this in the source:

let componentId = &quot;Island&quot;;
let componentExport = &quot;default&quot;;
let script = document.querySelector('script[data-island-id="ecac82eb-69f6-4e0a-896c-3ddde2c01f79"]');
let data = {
	componentExport,
	props: {},
	slots: {},
};

We'll need a different approach. I think it's only the actual props that could be vulnerable, because the component names aren't user-generated, but it is probably a legitimate issue.

@cramforce
Copy link
Contributor Author

I'll fix the encoding of quotes

@ascorbic
Copy link
Contributor

Reproduced the issue though:
image
image

@ascorbic
Copy link
Contributor

I think we would be safe to just escape </script>. This seems to be enough:

function safeJsonStringify(obj: any) {
	return JSON.stringify(obj).replaceAll('</script>', '<\\/script>');
}

@cramforce
Copy link
Contributor Author

@ascorbic You can circumvent that with all kinds of tricks. I can't for the life of me find a good npm package to do this. But it might exist. Added manual encoding for now

@ascorbic
Copy link
Contributor

That looks good. I just tried it and it does the job. Thanks for your help on this.

@ascorbic
Copy link
Contributor

This was the best I could find: https://github.com/mathiasbynens/jsesc?tab=readme-ov-file#isscriptcontext

@ascorbic
Copy link
Contributor

Of course all of these will be fixed when we start encrypting the props as planned

@ascorbic ascorbic merged commit ca335e1 into withastro:main Jul 19, 2024
13 checks passed
@astrobot-houston astrobot-houston mentioned this pull request Jul 19, 2024
@matthewp
Copy link
Contributor

Thanks! Patch should go out in a minute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: astro Related to the core `astro` package (scope)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants