Improving Third-Party JavaScript Security

Author: Krishna Chirumamilla, Manager, Secure Software Engineering

Chris Parkerson
Adobe Tech Blog

--

Most websites today include content from other sources. ​These types of third-party apps can provide everything from ads, analytics, widgets, videos, and other items that make the web more dynamic and interactive. Web developers then embed this third-party content into their web pages using tools like ​JavaScript. The most well-known example of third-party content is the social sharing buttons from Facebook, Twitter, Instagram, and other social media sites: The social media platforms provide an easy-to-embed JavaScript, and voila! You’ve now provided website visitors an easy way to tell the world they like your product.

But how do you know that JavaScript code is safe? Think about it: You’re embedding code that’s served from the third-party’s servers and not under your — the website owner’s — control. You have no idea what the third-party developer has done about security — and that can have serious consequences if you don’t take some simple precautions.

Before we get to those, let’s review the basics first.

Three Common Approaches

There are three popular ways to embed third-party JavaScript into a website. The first one, using the script tag src attribute, is simple. You just use the link provided by the third party ​and, during runtime, the browser sends a request to the third-party server and loads the script for the app to use its functionality. ​Here’s some sample code to see how this method works:

The second method that you can use to embed a third-party script is through a tag manager, such as Google Tag Manager or Adobe Dynamic Tag Management (DTM)​. Just like your content management system, which manages the content on your website, a tag management system manages the website tags, allowing you to insert bits of JavaScript, such as a Google Analytics tracking code. Tag managers typically offer a web-based interface to choose, edit, and manage those tags when they’re included in your web pages.​ But the ability to change the JavaScript that will be loaded on your website with the click of a button also introduces security issues, like embedding a seemingly innocuous — but in fact, malicious — JavaScript.

Here’s an example of the code to embed a JavaScript using a tag manager:

Tag management tools offer many advantages. First, they separate the process of adding and updating tracking tags from the process of altering your site’s templates and code. Which means you don’t have to make any changes to the code to add new JavaScript tags — and you can do this with the click of a button from the tag manager’s UI.

Tag management tools also help keep track of all the added tags, which helps ensure that the tags are properly organized, prevents the same tag from being added twice, and reduces mistakes during development. These tools also offer built-in debugging, testing, and preview capabilities when a JavaScript is added, removed, or edited on a webpage, as well as version control to keep track of changes.​ And finally, like all good tools, they allow admins to specify who can view, edit, and publish tags.

The third method to embed third-party JavaScript is to embed the code directly into the webpage. Here’s a sample of what this code looks like:

As you can probably guess, if you use this method, your site won’t be loading the latest version of the JavaScript, which means you’ll have to update and redeploy the app whenever you want to update to the latest version of the script. That’s the downside. The upside, however, is that this method offers the most security of the three methods, ​because you, not the third party, control the code that you’re embedding in your page.

​Real-world Examples of Poor Third-Party JavaScript Security

Now, let’s look at a couple of real-world examples of what can happen because of poor third-party JavaScript security.

Example #1

The vulnerable website includes a JavaScript library in a webpage. Unbeknownst to the website owner, the library pulls JavaScript from a hacked server — JavaScript that’s malicious and prompts the website’s users to unknowingly install malware. ​​

Example #2

Another type of attack targets not just one but thousands of apps at once. ​Here’s how: The attackers target third-party scripts being used in checkout pages. By targeting and compromising these scripts, attackers collect the credit card numbers of the users. ​Since many checkout pages use the same script, compromising just a single third-party script is enough for attackers to collect credit card numbers from thousands of websites.

In the image above, you can see that the website apps fetch malicious JavaScript from a hacked server. ​Then the malicious JavaScript sends the credit card info to the attacker. All this happens without users noticing anything out of the ordinary.

​(NOTE: Adobe provides guidance on how to help keep your Adobe Magento Commerce site, including the checkout page, safe from malicious JavaScript in the Adobe Magento Commerce Security Best Practices Guide.)

Inherent Risks of Third-Party JavaScript

Because these scripts are executed on the client side, all the risk is on you, not the JavaScript developer. And if you embed a third-party JavaScript in an unsafe manner, you’re enabling arbitrary code execution privileges on the client side.​

The second risk is that sensitive information can be inadvertently leaked to third parties — other than the owner of the JavaScript. Like in the attacks described above, attackers or other malicious individuals could extract PII, such as credit card numbers, etc. ​

And finally, there’s the risk that the third-party changes the JavaScript without notice, which means that they can change the code they’re executing on your website (the client side) as well as what information they are collecting. ​

The Missing Piece: Content Security Policies

Before discussing mitigation techniques, we need to talk about content security policies, because they are a key piece of the puzzle. ​A content security policy is an additional layer of security that helps to mitigate attacks like XSS, information leakage, etc. ​This is more of a browser security feature, but the server needs to tell the browser what to secure. ​

One popular way to do this is that a server sends content security policy directives in a CSP header. The browser reads the header and ensures that the directives are followed. ​In the following example, we have a default-src directive.

This directive tells the browser the exact origin from where all the content of the webpage should come. ​In the example, the server is saying the content should only come from example.com. Based on this, if the browser sees a request to fetch a JavaScript file from malicious.com, it won’t send the request. ​Similarly, there are directives that control what domains the requests are made to, what domain content js loaded from, etc.

Three Mitigation Techniques

Implementing Nonces

​The first mitigation method is to use your content security policy with a nonce. ​A nonce is a pseudonym for number used once, so the nonce changes every time a new session is created.

The script-src directive of a CSP tells the browser to load scripts from a specific domain or if a certain condition is met. ​Whenever you have a nonce in a script-src directive of a CSP, all JavaScript on the page must have the nonce attribute with the same nonce for these JavaScripts to be executed. ​

While this is a good first step toward third-party JavaScript security, it doesn’t validate what the JavaScript is doing. It’s more like telling the browser that we trust this JavaScript and it can be executed. ​If the owner decides to change the JavaScript, we won’t know that, and the script will still execute. Similarly, if the third-party’s server is hacked and the JavaScript is changed to do something malicious on the websites where it executes, the JavaScript will still execute — with malicious results. ​​

Putting JavaScript in IFrames

From a security perspective, putting the third-party JavaScript in an IFrame is a much more secure solution. First, it won’t give access to the webpage’s Document Object Model, or DOM. ​But modern JavaScripts, especially those that do analytics or tag management, need access to the DOM, and putting the JavaScript in an IFrame will hamstring the script’s intended purpose.

Using Subresource Integrity (SRI)

The final mitigation technique uses Subresource Integrity, or SRI​. In this method, the JavaScript is put through a hashing algorithm and the resulting hash value is used in the integrity attribute of the script tag​. When the browser loads the JavaScript from the third-party server, the browser also calculates the hash value​. If the hash value matches, then the script is executed. If the hash value doesn’t match, the script doesn’t execute and the browser displays the error in its console. ​

This is a great mitigation technique: It ensures that only the scripts that have been reviewed are executed. But while SRI works great for static third-party JavaScripts, modern tag managers dynamically change the script, which means that the JavaScript and the tags it loads can be changed at the click of a button.

How to Handle Dynamically Changing JavaScripts

When scripts are dynamically changing, SRI doesn’t make sense because whenever a script changes, the integrity attribute must also change. For a web developer, that means you need to re-deploy the entire app, which is exactly what using a tag manager tries to prevent.

So we’re back to where we started. ​ Now what?

In these scenarios, a good first step is to use a nonce with your CSP. Beyond that, you should consider where the script is being used. ​ If the script is executing on a sensitive page with password change or cart checkout functionality, it’s best practice to not include the script in those pages.

If you’re thinking of embedding a third-party script on a page where future script changes or sensitive information collection is not a big deal, you still may want to engage your own vendor security and legal teams to help review the third party’s security practices and posture before making any decisions.

Key Takeaways

Third-party JavaScripts can be risky if not properly maintained, but these risks can be mitigated using the three techniques outlined here. In some cases, it’s not possible to completely mitigate these risks, so reviewing the vendor’s security practices is recommended.

--

--

Manager of the Security Marketing Team at Adobe | Focus on the customer & make it happen | Foodie & cook | Gamer | Persistent wanderlust