0

I have a need to to create and attach a script tag to DOM at runtime. The script is a remote webpack bundle (via a Module Federation plugin). I would like to be able to change the URL to that hosted remote bundle at runtime (for A/B testing and debugging purposes). This is my own code, and I trust it as far as not having malicious code in it.

The code would look something like this

var myScript = document.createElement('script');
myScript.src = 'https://my.remote.domain.com/path/to/myScript.js';
document.head.appendChild(myScript);
... other code to make the webpack bundle run

My questions are:

  1. Is it safe to allow passing the https://my.remote.domain.com/path/to/myScript.js as a URL query param. Ex: https://my.site.com?scriptUrl=https://my.remote.domain.com/path/to/myScript.js? The code would look like this:

    var urlParams = new URLSearchParams(window.location.search);
    var myScript = document.createElement('script');
    myScript.src = urlParams.get('post');
    document.head.appendChild(myScript);
    

    It feels like this could open up a hole for an attacker to pass in a URL to an attacker script and execute it on my page. Am I on the right track here, or is this not a concern?

  2. What are the ways to secure the code above and allow the dynamic script attachments?

  3. If this code is an issue, what are the specific attacks that could happen here?

2
  • You correctly identified that this is a serious security issue. How to do it properly cannot be answered though since your only requirement is "I have a need to to create and attach a script tag to DOM at runtime.". To secure such an inherently insecure requirement one would need to understand what this script is needed for in the first place and what kind of limitations can be applied to the script, i.e. specific content, specific origin, maybe signed ... So please update your question to add the necessary details. – Steffen Ullrich Apr 21 at 14:19
  • Thanks for a quick response @SteffenUllrich. I added additional details "The script is a remote webpack bundle (via a Module Federation plugin). I would like to be able to change the URL to that hosted remote bundle at runtime (for A/B testing and debugging purposes). This is my own code, and I trust it as far as not having malicious code in it. " – HIT_girl Apr 21 at 14:32
2
  1. Is it safe to allow passing the [script URL] as a URL query param?

No, this is very dangerous. See question #3.

  1. If this code is an issue, what are the specific attacks that could happen here?

Since an attacker could pass any script into the URL, and have it run in your sites origin, you are basically opening yourself up to XSS attacks. That is very bad.

  1. What are the ways to secure the code above and allow the dynamic script attachments?

You need to somehow make sure that only scripts that you trust can be used. I can see two possible ways to do that:

  • Whitelisting. Instead of having the script URL as a query param, either have the value A or B for your A/B-testing. Then you keep a dictionary in your code of what URL A and B refers to. This way, only scripts you have allowed in the dictionary can be used.
  • Enforce that the script only comes from domains you trust. You will need to be careful about file upload functionality and open redirects with this solution though.

If not to impractical, I would go with the whitelist.

It might be tempting to use CSP for this, but I would strongly advice as using that as your only line of defense here. Browser support is not perfect, and it is easy to loose the header with a small server configuration mishap.

1

This is my own code, and I trust it as far as not having malicious code in it.

This is just an assumption. As long as this assumption is not enforced it can not be relied on. The current proposal allows to load script from arbitrary URL into your page, i.e. completely out of your control. This allows for an XSS attack.

To secure this you need to make sure that "This is my own code" is actually enforced. This can be done by only allowing script from origins you control. This can be for example a specific URL prefix, which restricts script loading to a specific path on the host you fully control. The URL then should only be loaded as script if it matches this requirement.

2
  • As far as securing this script, could this be done with proper CSP headers? I've read about adding integrity attribute to the script tag , would that be useful as well? – HIT_girl Apr 21 at 14:51
  • @HIT_girl: If CSP is sufficient depends on the browser, see caniuse.com/contentsecuritypolicy. In general CSP is more a defense-in-depth technology though. It can augment input validation but should not be used as a replacement for it. The integrity attribute on the script tag will unlikely work since you don't know its value up-front. And giving it as parameter and blindly trusting it is as insecure as given the URL as parameter and blindly trusting it. – Steffen Ullrich Apr 21 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.