Nº 03 · Guide · Cybersecurity · English

Best practices for securing third-party scripts on web pages

Client
undisclosed
Format
Best practices guide
Language
EN
THIRD-PARTY JS ✳SCRIPT INVENTORY ✳CSP ✳SRI ✳RUNTIME MONITORING ✳SUPPLY CHAIN ✳THIRD-PARTY JS ✳SCRIPT INVENTORY ✳CSP ✳SRI ✳RUNTIME MONITORING ✳SUPPLY CHAIN ✳
TL;DR · For the reader in a hurry
  • Third-party JavaScript is everywhere (median: 22 scripts per page) and runs with the same privileges as your own code.
  • If a vendor is compromised, so is your website: malicious script can access user data, form fields, cookies and session tokens.
  • Traditional server-side controls can’t stop client-side attacks at runtime.
  • Effective defense needs full visibility inside the browser: a live script inventory
  • + least-privilege script access + integrity checks with change detection and alerts + continuous runtime monitoring + compliance validation.

How to safely use third party scripts without blowing up my security posture

Introduction

Let’s be clear: if you run third-party scripts, you also run risks. Yet, in web development using third-party JavaScript is standard practice for functionality. It would be unproductive or even irresponsible to build everything in-house.

According to the HTTP Archive's 2024 Web Almanac overall, 92% of webpages use third-party resources. JavaScript files are the most common third-party resource type with roughly 30% of third-party requests. In 2024, the median mobile page made 22 JavaScript requests per page. In the 90th percentile, that number rose to 68. On the desktop, the numbers are in the same range with 23 and 70 respectively.

These numbers cover the story: how ubiquitous, third-partyJavaScript comes with real security and privacy issues.

In this post we look at practical best practices for third-party JavaScript security without sacrificing speed or functionality.

Why modern websites rely on third-party JavaScript

It’s good business practice for builders not to make their own bricks, but to rely on experts for materials and engineering. The same goes for web developers: they use third-party tools for analytics, online payments, widgets and other features that make websites dynamic and interactive.

There’s no need to reinvent solutions that already exist. Specialized tools get the job done so web teams can focus on core business instead of on user interface, A/B testing, online payment flows, analytics, location tracking and so on.

Why third-party scripts are a major risk for client-side security

Understanding third-party risk

The privilege problem

Here’s the issue: in the browser, all JavaScript is treated equally. The DOM doesn’t distinguish between your code and a vendor’s code. Third-party scripts get equal access to user data and form fields as your own first party code. They can read form fields, access cookies, modify page content, and make network requests. That is precisely the vulnerability that bad actors are looking for.

The supply chain problem

That means that if a vendor’s infrastructure is compromised, malicious scripts can be injected directly into your website.

At the median, 21% of scripts on mobile pages are injected dynamically. At the 90th percentile, the number of scripts is even 70% (https://almanac.httparchive.org/en/2024/javascript#injected-scripts – figure 1.14). On desktop, the numbers are comparable.

Injected scripts can create a security blind spot because they bypass browser security scanners. It also implies dynamically injected third-party scripts can even inject additional scripts you never approved of.

a breach at one of your vendors = a breach of your application

Even worse: a compromised script can cascade across every website using the script. A single weakness of a widely used script can turn into a large-scale supply chain attack.

Why traditional controls fail on the client-side

Traditional server-side controls won’t catch client-side breaches. They don’t see how JavaScript behaves in the browser at runtime. They’re looking in the wrong place.

On the one hand, a WAF is checking HTTP traffic to your server; other controls (i.e. dependency scans and package audits) analyze code before or at deployment. CSP, on the other hand, is enforced at runtime. It sets rules and restricts where scripts load from, but it doesn’t monitor what’s happening when a trusted source is infected and serves malicious code.

Even with fully operational traditional security controls, organizations are operating blind to client-side attacks and breaches can stay undetected for weeks or even months.

Real-world risks of third-party JavaScript in the browser

So here we are now, running dozens of external scripts, trusting them with full privileges. It all comes down to trust: we picked our vendors, CSP defined the sources. And we’re much more productive and dynamic. All good reasons to trust the process. So far, so good.

What could possibly go wrong?

What if one of your trusted vendors gets compromised? Your client-side becomes the attack surface. Attackers inject malicious code into legitimate scripts that run with full access to client data and form fields, exposing PII and stealing payment data. That’s exactly what happens in Magecart or e-skimming attacks (link): malicious JavaScript copies form data and exfiltrates it to attacker-controlled servers. This is what happened in the case of the 2018 British Airways breach (link). Attackers injected malicious code into a third-party script. And PII and payment card details of 380,000 customers were stolen.

It’s sophisticated and doesn’t even look like data exfiltration. It’s data exfiltration disguised as normal analytics traffic. When the infected third-party script loads, the browser contacts the vendor’s server and exposes IP addresses, cookies, referrer data and request headers. Form fields, session tokens and user PII, passwords and payment data can be copied and stolen. Your server controls? They won’t raise the red flag.

You trust what you don't see. A script that worked fine during testing, can be manipulated at the source. The moment you allow scripts to load from external servers, you lose control in the user’s browser.

the risk of third-party scripts = the risk of external control

You trust vendors to safeguard script integrity. Vendors need to push updates, security patches, fix bugs and add new features. These updates deploy automatically if there’s no version control. When attackers find a vulnerability with one of your vendors and inject malicious code into an update, every website using the script gets hit in a JavaScript supply-chain attack.

Other dangers are just around the corner. Attackers can target vendor CDNs, abuse tag managers or even more audaciously attack infrastructure providers. As a result, you have allowed compromised scripts to run in users’ browsers. User data is exfiltrated from the browser while your code base looks clean, and your repository shows no changes.

There you go: malicious browser-side data exfiltration that looks like normal analytics traffic.

Best Practices for Securing Third-Party Scripts

Once allowed, scripts run freely. When a vendor gets compromised or a CDN is tampered with, malicious code can slip into the users’ browser. What now? Scratching your head about how to bolster your defense?

You’re not alone. But there are practical steps you can take today.

Complete Script Inventory and Visibility

Your first defense is visibility and that means creating an inventory.

There’s no guarantee that the scripts you approved during development are what load in production. And if you can’t see it, how could you possibly secure it?

The browser doesn’t care what you approved in a pull request. It executes whatever it’s told to execute. The user’s browser may be running code that never shows in your HTML or your repository. At that point, “approved dependencies” is just a concept, not a defense. Code running without your approval… You really think you’re in control?

no inventory = no visibility = no control

That’s why a live, dynamic, catalogue of every script running in the browser is a good start. It‘ll show where code loads from: a third-party vendor or some obscure fourth party?

Next on the list: check if scripts change and how often they update. But even more importantly, verify what data they touch and ask yourself: why? Watch closely for scripts that access sensitive personal data, form fields, cookies, session tokens and so on.

Payment pages especially need your attention. In a perfect world, there shouldn’t be any third-party scripts on payment pages. Zero risk. But that’s not the case: payment processors, like PayPal or Klarna, require JavaScript for example for payment flow and fraud detection. And businesses need that functionality. Verizon's 2024 Payment Security Report pointed out that on payment pages across 7,000 sites over 51,000 scripts were found. That’s over 7 scripts per payment page.

With live inventory, you’ll spot threats early before they cause damage.

Least-privilege Script Access

Once you know what scripts are running and what they can do, ask what data they really need to access. Not every script requires full privileges.

Why would an analytics script need access to payment data? Marketing pixels have no business reading login and password, right?

By default, browsers will run any scripts, including chained scripts. Restricting access to data is critical for your defense. A Content Security Policy (CSP) defines where code can load from: e.g. only your own servers and whitelisted sources. You set those rules in your HTTP headers or HTML, and the browser will enforce them.

CSP only checks where code loads from, but not what it does once it’s running. Code is dynamic and gets updated. If malicious code loads from a trusted source, your CSP won’t block it.

That’s why your CSP needs to be very specific. Wildcards like script-src *, unsafe-inline or unsafe-eval() allow untrusted code to execute at runtime and weaken your CSP.

CSP isn’t full defense, but it limits the attack surface.

Check integrity, detect changes and set alerts

Next in line: Subresource Integrity (SRI). SRI adds a cryptographic hash to scripts or link tags. It acts as a guarantee for the integrity of the code. When the browser loads a script, it checks the hash. If one byte is different, the browser will not run the code.

SRI works well to protect static third-party assets and catches CDN level modification. But that doesn’t mean it’s 100% bulletproof: it doesn't control where scripts load from, nor does it control behavior. It only checks if the file matches the hash. If you attach the hash to a malicious update, SRI will validate it anyway. It doesn’t control behavior and won’t stop the browser from running compromised scripts.

Integrity checks alone aren’t enough. Change detection and alerts are needed. Flag unapproved scripts or scripts that suddenly touch fields they shouldn’t have access to. Headless browsers are a useful technique to automate monitoring and catch threats early.

Runtime Monitoring

Runtime monitoring catches compromised scripts from trusted sources. This is perhaps the most important layer of your defense. It catches what CSP and SRI miss.

At runtime, where scripts came from or if they changed don’t matter. What matters is what they're doing. So, watch for behavioral anomalies.

When a script suddenly starts reading form fields or making network requests, check your inventory and block it. Runtime monitoring is watching scripts in action. Track DOM manipulation: is something modifying your payment page?

Your new routine: investigate event listeners attached to sensitive data. Where is data flowing? Monitor network requests. Check what scripts access cookies and the data they send. Check your inventory when a script is behaving differently,

At runtime, there’s no time for guesswork. Monitor and verify.

Compliance Alignment

Compliance has a bad reputation for time-consuming paperwork and audits at the worst time.

But they are catching up to client-side risks and that’s actually very helpful.

Compliance formalizes good practices: inventory, integrity checks, runtime monitoring, change detection. In general, they don’t add new controls. They impose a accountability and that comes with continuous visibility and monitoring. When things go wrong, you need logs and reporting to prove correct controls were in place.

PCI DSS v4.0.1 specifically requires monitoring and blocking client-side script payloads (requirements 6.4.3 and 11.6.1). GDPR requires monitoring and disclosing data collection by client-side scripts. CCPA requires listing what information is collected and whether it's shared with third parties.

Sound familiar?

When a breach happens auditors will ask questions. What scripts were running? Did you monitor them? Can you prove it? A failed audit can lead to regulatory fines and legal exposure.

FAQ

Why are third-party scripts a security risk?

Because third-party scripts execute at runtime with the same privileges as first party code. They can access and read form fields, cookies, session tokens, modify the DOM, and make network requests.

If a vendor’s infrastructure is compromised, malicious third-party JavaScript can be injected into the users’ browser. The scripts can load other scripts you never approved. If widely used scripts are tampered with, they can cascade across thousands of sites in a supply-chain attack.

Why do traditional controls fail to stop client-side attacks?

Traditional security controls (e.g. WAF, dependency scans) operate on the server side. They inspect requests and code before deployment or at the server. What JavaScript does during runtime is invisible to server-side controls because attacks happen client side, in the user’s browser. CSP? CSP operates client side and only checks where scripts load from, not what they do.

Does CSP protect against malicious third-party code?

CSP reduces the attack surface. It defines where scripts can load from: it whitelists sources and blocks scripts from unauthorized domains. But it only checks the source, not the behavior. If malicious code is loaded from a trusted source, CSP won’t stop it from running. CSP is not sufficient on its own and needs to be combined with runtime behavioral monitoring and integrity checks.

Can SRI prevent third-party script breaches?

Not completely. SRI checks file integrity, not behavior or vendor compromise. SRI adds a cryptographic hash to a file to ensure it hasn’t been modified during transfer. It works well for static third-party code and helps detect CDN tampering and man-in-the-middle modifications.

But SRI cannot protect against compromised scripts or malicious updates from the original source. JavaScript is often updated dynamically. If a vendor serves malicious code and developers update the hash to match the file, SRI will validate it. Like CSP, SRI needs to be combined with other defense strategies.

What should security teams do first?

Start with a live inventory: without runtime visibility into what scripts are running, you can’t secure scripts you don’t see. The inventory will show you where code loads from. While you're at it, also check changes and updates. But more importantly, verify what data they touch and ask yourself: why?

Why should payment pages avoid third-party code as much as possible?

Payment pages are primary targets for attackers because they collect the most sensitive data: PII and payment card details. If a malicious script runs on a payment page, it can steal this data as users enter it.

The consequences are substantial: regulatory exposure, reputational damage, legal proceedings with damage claims and financial losses. Eliminating them completely isn’t feasible: payment processors often require JavaScript for fraud detection. Every script represents a potential breach point. Minimize scripts: marketing and analytics or chat widgets don’t belong on payment pages. For the strictly necessary scripts: runtime monitoring is non-negotiable.

More writing
← Previous
How e-skimming steals credit card data and how to stop it
Read →
Next →
What is CSS? Mastering styles and security
Read →