1. 19
  1. 13

    Elm checks and disables event handlers and anything whose value looks like a JavaScript URI such as above. The problem is once again that browsers are quite lenient with the javascript: part. Yes, it accepts uppercase characters, but Elm did properly check for that. In this case, the problem was that it was possible to have tabs inside the URI. Meaning that to a browser, Java\t\tscr\tiPt:alert('Hi') is an acceptable JavaScript URI. Note that the browser ignores tabs but not spaces.

    Note that the browser ignores tabs but not spaces.

    Wow.

    1. 5

      This is all the more reason to always be setting a CSP even when you think you don’t need it.

      1. 3

        This is very interesting but it looks so error prone? Maybe I misunderstand, because I’m not super versed in Elm things.

        If Elm is building an abstraction on top of the DOM, do you want to end up enumerating all the possible badness? Wouldn’t it be preferable to build a sanitizer (or build upon an existing sanitizer) instead?

        In terms of threat modeling: If you’re worried about a bad elm package in your dependency tree, shouldn’t you be worried about all sorts of attacks on everyone (developers and users) in a way that XSS becomes the least of your problems?

        1. 2

          do you want to end up enumerating all the possible badness?

          For now, all of the sanitizing that is occurring is included in these lines of code: https://github.com/elm/virtual-dom/blob/1.0.3/src/Elm/Kernel/VirtualDom.js#L288-L329 These are all the things it does:

          • For attribute/property keys:
            • Replace script tags by p tags
            • Prefix attributes whose name start with “on” with “data-”
            • Replace “formAction” attribute and property by “data-formAction”
            • Replace “innerHtml” property by “data-innerHtml”
          • For attribute/property values:
            • Replace “javascript:” and “data:text/html” URIs by empty strings (or by warnings in development mode)

          That is currently all that is being done. I personally feel like it’s super lightweight. I’m curious what kind of error-proneness you have in mind.

          I am unsure what you mean with sanitizers? Do you mean the tools/functions that escape your values (replace < by &lt; etc? I am not familiar with all the things that they do, but my gut feeling would be that they likely do more work than necessary here? I also don’t know how well that works with a virtual DOM approach where you can’t arbitrary inject HTML code. But checking whether a value starts with javascript: sounds a lot faster than escaping all the dangerous characters in a potentially big string?

          In terms of threat modeling: If you’re worried about a bad elm package in your dependency tree, shouldn’t you be worried about all sorts of attacks on everyone (developers and users) in a way that XSS becomes the least of your problems?

          I think that all of these issues should be addressed as much as possible. The nice thing with Elm is that since it starts from scratch, there are very few places where security issues can pop up. Where they pop up, we fix them. If we’ve fixed all of the known issues, then as long your core Elm dependencies (aka the Elm building blocks) up-to-date, then whatever is attempted anywhere in your dependency tree will be made ineffective (pending discovery of new issues). That is at least the goal in my opinion.

          Let me know if I misunderstood any of your questions!

          1. 1

            I’m sure there are things I didn’t fully get either. For example, I’m not sure whether the issue is with static string assignments to “dangerous” attributes or if you’re only guarding assignments through user input in virtualdom or both. Secondly, I’m not sure if this is about user-supplied values for specific attributes or completely user-controlled HTML.

            I tried fiddling with things at https://elm-lang.org/try, but it looks like this is still using the unpatched version. Also, given the questions above I’m not sure what test code would look like.

            That all being said, there are still issues if I took the strictest interpretation of these questions. I believe there are potential issues with e.g., encoding/escaping/entities and obscure markup that changes after insertion (mXSS and svg animate elements).

          2. 1

            I believe there might be bugs with URL encoding? The regex seems to be looking for javascript: with whitespaces in between, but javascript%3A would also work?

            1. 2

              From my testing, <a href="javascript%3A alert(1)">XSS</a> is not considered as a JavaScript URI, but rather a link that points to “/javascript%3A%20alert(1)”. Meaning it will be a broken link, not a security issue that allows you to execute arbitrary code. Let me know if you find anything else though!

              1. 1

                Depends on the browser, I guess.

                1. 1

                  Oh, I only tried it in Chrome. Which browser did you make it work in?

                  1. 1

                    The URLs data:text/html,<a href="javascr%0aipt:alert(2)">click me (newline within the scheme) and data:text/html,<a href="javascript%3Aalert(2)">click me (colon replaced with url encoding) alert in Safari and Firefox and Chrome Canary.

                    What am I missing?