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(extension-link): make the javascript link detection case insensitive #5153

Closed

Conversation

julmud
Copy link

@julmud julmud commented May 15, 2024

Changes Overview

The fix for the XSS vulnerability in #4602 does not make the check on javascript URL in a case insentive way.

Implementation Approach

Convert the href attribute to lowercase before testing if it starts with "javascript:"

Testing Done

Increased the Cypress test coverage and ran it.

Verification Steps

Verify non-breaking on link and youtube extension, and ensure the new tests pass.

Checklist

  • I have renamed my PR according to the naming conventions. (e.g. feat: Implement new feature or chore(deps): Update dependencies)
  • My changes do not break the library.
  • I have added tests where applicable.
  • I have followed the project guidelines.
  • I have fixed any lint issues.

Related Issues

#3673
#4600
#4602
#5157

Copy link

netlify bot commented May 15, 2024

Deploy Preview for tiptap-embed ready!

Name Link
🔨 Latest commit 0ac4249
🔍 Latest deploy log https://app.netlify.com/sites/tiptap-embed/deploys/6645a497ed75330008435faa
😎 Deploy Preview https://deploy-preview-5153--tiptap-embed.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

nperez0111
nperez0111 previously approved these changes May 15, 2024
Copy link
Contributor

@nperez0111 nperez0111 left a comment

Choose a reason for hiding this comment

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

We should definitely release this

@@ -163,7 +163,7 @@ export const Link = Mark.create<LinkOptions>({
renderHTML({ HTMLAttributes }) {
// False positive; we're explicitly checking for javascript: links to ignore them
// eslint-disable-next-line no-script-url
if (HTMLAttributes.href?.startsWith('javascript:')) {
if (HTMLAttributes.href?.toLowerCase().startsWith('javascript:')) {
Copy link
Contributor

Choose a reason for hiding this comment

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

oof good catch

Copy link
Contributor

Choose a reason for hiding this comment

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

I just tested this locally and it looks like you can fool it with leading white space too. I think that besides the protocol (e.g. https://) a colon is invalid so may this should be an .includes instead of a .startsWith

Copy link
Author

@julmud julmud May 15, 2024

Choose a reason for hiding this comment

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

It gets tricky if the URL uses basic-auth and includes the username and password (i.e., https://javascript:my_password@example.com/ for a user named javascript would be a false positive when using .includes). I think it'd be better to .trim() before calling .startsWith()

Edit: and a colon is valid in the path part of an URL, as long as it's not the first part of a relative path according to RFC 3986. (BTW, it's also used as a delimiter for the port number if needed.)

Copy link
Author

Choose a reason for hiding this comment

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

I think the correct way to do this would be to extract the scheme (everything up to the first colon), trim it, and then do a case insensitive match for javascript. I'll push something later today.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hello! Happy to see that you're looking into fixing this. ❤️ However I think there are a few issues with your approach here.

  • it would allow javascript protocol when it includes \x01-\x20 characters inside the javascript:
  • it would allow javascript protocol when it includes whitespace characters before the colon javascript\n:.

It's really hard to get the blacklisting approach right. I made a PR where I try to use a whitelist approach instead, see here: #5160 It's still draft/WIP though.

I've taken inspiration from DOMPurify (using it might in general be a good approach for tiptap).

I've also created test cases from PortSwiggers XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#protocols

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for chiming in @chroth we are looking into the right approach for this sensitive topic and your contribution made us re-think some things

There are three open PRs for XSS vuln fixes:
#5157
#5160
#5153

@benja
Copy link

benja commented May 15, 2024

will this be released as soon as merged?

@julmud julmud force-pushed the bugfix/case-insensitive-sanitization branch from f95429c to 0ac4249 Compare May 16, 2024 06:15
@julmud julmud requested a review from nperez0111 May 16, 2024 06:19
Copy link
Contributor

@nperez0111 nperez0111 left a comment

Choose a reason for hiding this comment

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

lgtm

@nperez0111
Copy link
Contributor

We ended up resolving it with this #5160

But we appreciate your contribution, your work was helpful in the final fix.

We did this a bit strangely because of the multiple PRs and the urgency of it

@nperez0111 nperez0111 closed this May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

4 participants