The code you ship but never wrote
Open the page your customers see and count the scripts. The analytics tag, the chat widget, the A/B testing snippet, the consent banner, the payment SDK, the font loader, the session-replay tool — each one is JavaScript that runs inside your page, with the same access your own code has. It can read every form field, every cookie not marked HttpOnly, every keystroke on the checkout page. You didn't write it, you can't see its source, and it updates whenever the vendor pushes a change — silently, on their schedule, straight into your customers' browsers.
This is the web supply chain, and it's the half of software supply chain security that an SBOM doesn't capture. An SBOM tells you what you build; it says nothing about the third-party code you load at runtime from a domain you don't control. For a lean team that leans heavily on SaaS widgets to ship fast, this is often the largest piece of untrusted code in production — and the one nobody has inventoried.
How a friendly widget becomes a skimmer
The attack pattern has a name — formjacking, or Magecart — and it's brutally simple. An attacker doesn't breach you; they breach a vendor whose script you load. The vendor pushes a tampered version of their widget, and because your page loads it fresh on every visit, the malicious code runs on your site, against your customers, the moment the vendor's CDN serves it. The classic version skims credit-card fields off a checkout page and exfiltrates them to an attacker-controlled domain — and your servers, your logs, and your monitoring never see a thing, because the theft happens entirely in the browser.
The damage is yours regardless of whose code did it. From the customer's perspective, from a regulator's perspective, and from a breach-notification perspective, data skimmed off your checkout page is your incident. "It was the vendor's script" is an explanation, not a defense.
Inventory first: you can't constrain what you can't list
Every fix starts with knowing what's actually loading. Most teams are surprised by their own page:
- Enumerate every external script and origin. Browser dev tools, your tag manager's config, and your page source together tell you what you load and from where. A tag manager is itself a risk to flag — it can inject new scripts without a code deploy, which means scripts can reach production without passing through change control.
- Decide what each one is allowed to touch. A font loader has no business near the checkout form; a payment SDK does. Mapping scripts to the data they can reach is the same data-classification discipline applied to runtime code — the script on your payment page earns the strictest scrutiny.
- Cut what you don't need. Every script you remove is a supply-chain dependency you no longer have to trust, monitor, or explain to an auditor. The same tool-sprawl logic applies to widgets: unused third-party code is pure risk with no upside.
The controls that constrain untrusted scripts
You can't read every vendor's source, so you constrain what their code can do and detect when it changes:
- Content Security Policy (CSP). A CSP allowlist of script origins is the single highest-leverage control here: it stops the browser from loading or exfiltrating to domains you didn't approve, which neutralizes the most common skimmer exfiltration path. CSP lives alongside your other HTTP security headers and deserves the same care.
- Subresource Integrity (SRI). For scripts loaded from a fixed URL, an SRI hash tells the browser to refuse the file if its contents change. If a vendor's CDN serves a tampered file, the hash mismatches and the browser blocks it. SRI doesn't work for scripts that legitimately change often, which is itself a useful signal about which vendors you're trusting blindly.
- Isolate the riskiest flows. Where the data is most sensitive — card entry, especially — prefer payment integrations that move the actual fields into a vendor-hosted iframe, so a compromised marketing script on your page literally cannot read the card number. Reducing what a script can reach beats hoping it stays honest, the same least-privilege instinct applied to the page.
- Monitor for drift. CSP report-only mode and violation reporting turn an unexpected new script origin into an alert instead of a silent breach, feeding the same detection pipeline as the rest of your program.
Treat a script change like any other finding
When monitoring flags a new origin, a CSP violation, or an SRI mismatch, that's a finding with an owner and a clock — ranked by what page it's on. A new unapproved script on the checkout page is a five-alarm fire; a changed font on the blog can wait behind it. This is the same exposure-first triage you run everywhere else, and the inventory of who-loads-what feeds your answers to security questionnaires, which increasingly ask exactly this question.
One honest caveat: a platform can inventory the third-party scripts your pages load, flag new or changed origins as findings, track who owns each fix, and keep that evidence current — it organizes and proves the work. It does not write your CSP, deploy your SRI hashes, re-architect your checkout into an iframe, or grant or guarantee any certification; those are operational and engineering steps your team owns, and which obligations (PCI scope especially) apply to you is a question for counsel and your payment processor.
Every third-party script on your page runs with full access to the page your customers trust, and when a vendor is compromised, the skimmer runs on your site against your customers while your servers stay clean. An SBOM won't catch it because this is code you load, not code you build. Inventory every external script, cut what you don't need, constrain the rest with CSP and SRI, isolate the card fields behind a vendor iframe, and monitor for drift. The data skimmed off your checkout is your incident no matter whose code did it — so own the code you didn't write.