Skip to main content
PCI Monitor

Third-party JavaScript risk: supply chain attacks on payment pages

Threats · 7 min read · Last reviewed: October 17, 2026

Every third-party script on a payment page runs with the same access as your own code: it can read the form, change the page and send data anywhere. If the company that serves that script is breached, sells its domain or simply ships a bad update, your customers' browsers run the attacker's code. This is a software supply chain risk, and it is the main way client-side card theft reaches well-defended merchants.

Why a third-party script is so powerful

Modern websites are assembled from many sources. A typical page loads analytics, advertising and conversion tags, a chat widget, a customer-feedback tool, fonts, A/B testing, a consent banner, and often a tag manager that loads still more. Each of these is JavaScript from another company's server.

When a browser loads a script with a normal <script src="..."> tag, that script is not sandboxed. It runs in the context of your page, with the same permissions as code you wrote yourself. It can read every field of a payment form, add or remove elements, listen to key presses and make network requests to any address that the page's security policy allows. The browser does not know which scripts you trust more than others.

So the security of your payment page is only as strong as the weakest company whose script it loads, and as the weakest company that company loads from.

How a third-party script becomes a skimmer

Attackers do not need to break into your site if they can break into something your site already trusts. The documented routes include:

  • The vendor is breached. An attacker alters the vendor's script on the vendor's own servers, and every site that loads it now serves the modified code.
  • The domain or account changes hands. A script host's domain is sold, expires and is re-registered, or the vendor's account is taken over, and the new controller serves different code from the same address.
  • A script loads other scripts. You approved script A, but A loads B and B loads C. A change at the end of the chain is invisible if you only look at the first link.
  • Content that varies by visitor. Some services generate their script on the fly, for example depending on the visitor's browser or location. A malicious version can be served to some visitors and not to others, including not to the people who test it.
  • A bad or malicious update. Vendors push new versions without telling customers, and a mistake or an insider can introduce harmful behavior.

The chat-widget case described in notable client-side card theft incidents is an example of the first route. The next section describes an example of the second.

A recent example: the polyfill.io domain

Polyfill.io was a popular free service that served JavaScript compatibility code for older browsers, and many websites loaded it directly from the cdn.polyfill.io address. On 25 June 2024 the security firm Sansec reported that code served from that domain was injecting malicious behavior, and estimated that more than 100,000 websites embedded it. Sansec's report says the domain and its associated GitHub account had been acquired by a Chinese company in February 2024; after that, the malicious behavior began. The code Sansec analysed redirected some mobile visitors to unrelated sites and was written to avoid detection, for example by skipping visitors who looked like administrators.

In response, Cloudflare began rewriting requests for the domain to its own safe mirror, and the domain registrar placed the domain on hold. Later counts by other researchers put the number of affected sites higher than the first estimate, so treat any single figure as an estimate.

The behavior Sansec saw was a redirect rather than card theft. The lesson for payment pages is about the position the script held: a script served from that address could do on any page what it was doing on those pages, including reading a payment form. No site had been hacked in the usual sense; its own code had not changed.

How to manage the risk

Reduce what you load

The most effective step is to load fewer third-party scripts on pages that handle card data. Payment pages rarely need advertising tags, heat maps or social widgets. Many organizations separate the checkout from the marketing site for exactly this reason.

Know what you load

Keep an inventory of every script on each payment page, who approved it and why it is needed, as described in how to build a payment page script inventory. This is also what PCI DSS 6.4.3 asks for; see the explanation of requirement 6.4.3.

Pin and restrict

  • For static third-party files, use Subresource Integrity so the browser refuses a file whose content has changed.
  • Where the license allows it, consider hosting a pinned copy of a library yourself and updating it deliberately, instead of loading it live from someone else's server.
  • Use a Content Security Policy to limit which origins can supply scripts, and where data can be sent.
  • Where a widget does not need access to the page, load it in an iframe with the sandbox attribute.

Govern the vendor

Treat script providers like any other third party: understand who they are, what the script does, how they secure their delivery and how they will tell you about changes. PCI DSS requirement 12.8 covers managing third-party service providers.

Watch for change

Because a vendor can change a script at any time, an approval on the day you added it is not enough. Compare what your pages actually load against the approved list on a schedule, and watch for expiring or changed ownership of the domains your scripts come from. See how to detect client-side tampering.

Key takeaways

  • A third-party script has the same power as your own code; the browser does not limit it to the tasks you had in mind.
  • Routes to compromise include a breached vendor, a changed or expired domain, chains of scripts that load other scripts, and content that varies by visitor.
  • The 2024 polyfill.io case showed that a trusted address can start serving harmful code without any change on the sites that use it.
  • Load fewer third-party scripts on payment pages, keep an inventory with approvals, and pin or restrict what remains.
  • Approval at the time of adding is not enough; monitor what is actually delivered.

Frequently asked questions

What is a JavaScript supply chain attack?

It is an attack in which the attacker compromises a script, library or service that many websites load, so that the malicious code reaches all of those sites at once without the attacker having to break into each one.

Does Subresource Integrity solve third-party script risk?

It helps with static files from a fixed address, because the browser blocks a file that no longer matches its hash. It cannot help with scripts that are generated per visitor or updated frequently, or with scripts loaded by other scripts. See the article on Subresource Integrity.

Is hosting a copy of the library myself safer?

It removes the risk that the vendor's server changes the file behind your back, but you become responsible for updating the copy and for any vulnerabilities in it. It works best together with an approval and update process.

Should payment pages load analytics and advertising scripts?

Each one widens the attack surface, and many organizations choose not to load them on the payment page. If you do, each needs a written reason, an approval and monitoring. PCI DSS 6.4.3 applies to every script on the payment page.

References

Last reviewed: October 17, 2026