Analytics, advertising, chat, payment widgets, libraries from a CDN: most sites load code they did not write on every page view, and that code runs with the same privileges as the site's own scripts. This guide explains how to find out what is running, limit what it can do, and notice when it changes, based on OWASP and MDN. It does not describe how attacks work.
Why third-party scripts are a risk
The OWASP Third Party JavaScript Management Cheat Sheet groups the risks of embedding third-party JavaScript into three.
- Loss of control over changes
- There is usually no guarantee that the provider's code stays the same as when you developed and tested against it. The provider can push new features at any time
- Arbitrary code runs on users' devices
- Third-party code is rarely reviewed before it is added, and it runs with the same privileges as the user. OWASP also describes a provider domain expiring and being re-registered by someone who then publishes malicious code
- Disclosure of information to third parties
- When the script loads, the browser connects directly to the provider's servers, which receive the IP address and any cookies the provider set earlier
A tag manager adds another layer. OWASP explains that what a tag manager returns can be changed from its web interface and is deployed instantly: the next page view runs the changed code. Reading your site's source code therefore does not tell you everything that actually runs.
This site has covered incidents of this type: the Polymarket third-party script incident and the possible card data leak at the APORITO online store. In both, the problem was code running on the page the user was looking at.
Your page (content, form input, cookies)
↓ runs inside the same page
Your own scripts
You review and serve them
Third-party scripts
The provider can change them. They can read the page
Forms posting elsewhere
Input goes to another origin
↓ how to limit them
Inventory and removal
SRI / self-hosting / CSP script-src and connect-src
CSP form-action
How to defend: six steps
List every third-party script that runs
Start with an inventory. Include scripts written directly into your HTML, tags configured in your tag manager, and anything a library or plugin loads on its own.
For each one, record the origin it loads from, whose service it is, why it was added, which pages it runs on, and who switches it off, and how, if something goes wrong. Also list iframes, images and other resources that connect to outside servers; the list then doubles as the input for your CSP.
Remove what you do not use, and cut back on sensitive pages
Anything in the list with no known purpose or no owner is a candidate for removal. Old campaign tags and analytics services you have already replaced are often still there.
On pages where input is valuable, such as login, payment, password or email changes, and admin screens, keep only what is needed. A tag placed in a site-wide template also lands on these pages, so decide per page type what loads. For widgets that do not need to touch the page, OWASP describes isolating them in an iframe on a separate domain with the sandbox attribute.
Restrict who can publish in the tag manager
OWASP warns that a data layer (the object holding values passed to tags) is not a sandbox, and that tag-manager containers can run custom JavaScript and HTML tags. It recommends restricting publishing access and reviewing changes as you would application code.
In practice, start with four things: limit publishing to a few people, turn on two-factor authentication for tag-manager accounts, disable custom HTML tags if you do not need them, and have a second person review before publishing.
Add SRI to fixed files, or serve them from your own site
SRI (Subresource Integrity) lets you put a hash of the file in an integrity attribute on <script> and similar elements; if the file the browser receives does not match, it refuses to load it. According to MDN, the allowed hashes are sha256, sha384 and sha512, a cross-origin file needs the provider to allow CORS, and you also add the crossorigin attribute.
SRI only works for files whose content does not change, such as a versioned library. On an analytics tag that the provider updates at will, every update breaks loading. In that case, serve a reviewed copy from your own site (what OWASP calls in-house mirroring) or do not load it on sensitive pages. To check libraries for known vulnerabilities, paste your lockfile into the dependency vulnerability scanner.
Restrict sources and destinations with CSP
In your Content-Security-Policy, allow the origins from your step 1 list. script-src restricts where scripts load from; connect-src restricts where fetch, XMLHttpRequest, WebSocket, EventSource, sendBeacon and similar APIs can connect (MDN).
form-action, which restricts where forms submit, does not fall back to default-src. MDN states that not setting it allows anything. If your forms only post to your own site, set form-action 'self' explicitly.
Enforcing a new policy at once can break legitimate features, so collect violation reports first with Content-Security-Policy-Report-Only. MDN notes that reports are only sent if you specify report-to, and that this header is not supported in a <meta> element (the deprecated report-uri also still works). You can try policies in the CSP Builder; for headers in general, see choosing security headers.
Make changes visible, and decide in advance how to switch scripts off
Third-party scripts change without any action on your part. At a fixed interval, for example monthly, compare your list with what actually runs, and investigate any unknown destination that appears in CSP violation reports. Subscribe to the providers' security notices.
Document which tag is switched off, by whom, and from which screen when something goes wrong. If you run card payment pages, also note that PCI DSS v4.0.1 requirements 6.4.3 and 11.6.1 on payment page security have been effective since 31 March 2025 (PCI SSC). For merchants that validate with SAQ A, whose account data functions are fully outsourced to compliant third parties, those two requirements are replaced by an eligibility criterion to confirm that their site is not susceptible to attacks from scripts that could affect their e-commerce systems; the requirements in the standard itself do not change.
What each control does and does not stop
| Control | Stops | Does not stop | Best for |
|---|---|---|---|
| Removal | Every risk tied to that script | — | Scripts with no known purpose, or unused |
| SRI | Replacement of the file in transit or at the provider | What an untampered script sends as part of its normal function. Loading breaks when the provider updates the file | Versioned, fixed files |
| Self-hosting | Replacement at the provider | Old versions linger unless you update them yourself | Libraries you have reviewed and keep using |
| CSP | Loading from origins you did not allow, and requests or form posts to destinations you did not allow | Compromise of an origin you did allow. Data sent to an allowed destination | Every page (roll out gradually) |
Easy to spread
- Tags sit in a site-wide template
- Many people can publish in the tag manager
- No CSP, or no
form-actionin it - No list of third-party scripts and no agreed way to switch them off
Under control
- Tags are loaded per page type
- Few people can publish, and a second person reviews changes
- CSP pins script sources, connection destinations and form destinations
- A list exists and is compared with reality on a schedule
Check the result with the Site Transparency Checker
Once you have a list, compare it with what is actually on the page. Enter the homepage URL of a site you manage into the Site Transparency Checker, and it reports the following from the fetched HTML.
- External script/resource origins
- Other origins referenced by script, iframe, img and link (stylesheet, preload and similar). Anything not in your step 1 list needs an explanation
- Analytics / ad tags (tracking)
- Common analytics, advertising and monitoring services, shown by name. The name classifies the destination; it is not a safety verdict
- Unknown third-party scripts (could read input)
- Scripts loaded from another origin. No script is judged safe because its provider is well known
- Forms posting externally
- A form action or button formaction pointing to another origin. If you did not intend it, check it first and pin it with CSP form-action
- Sets a cookie
- Whether the fetched response sets a cookie. Cookies set by JavaScript are not checked
The tool has limits. It fetches only the homepage (including language homepages and index.html), does not run scripts, and does not fetch embedded files. Scripts loaded later by a tag manager, and requests that only happen when a button is pressed, are not visible to it. So also do the following.
- Open the page you want to check (including login and payment pages) and open your browser's developer tools
- Record in the Network tab, and use the page with dummy data
- Look for requests to external domains that are not in your list
- After setting CSP, confirm with the Security Headers Checker that the header is actually returned
If you run a site in Japan: the external transmission rules
According to Japan's Ministry of Internal Affairs and Communications (MIC), a June 2022 amendment to the Telecommunications Business Act introduced rules so that users can see when tags or data-collection modules send information about them to third parties (in force since 16 June 2023). The rules apply to those operating a telecommunications business; MIC lists messaging, social networking, search, and information services such as news and aggregation sites as typical cases, and says online sales of a company's own products, corporate websites and personal blogs are not telecommunications businesses and are out of scope.
Where the rules apply, the operator must notify users of, or make easily available to them, what information is sent, the name of whoever handles it, and the purpose. Your step 1 list is a good starting point for that disclosure. Check MIC's explanation and flowchart to see whether you are covered.
This site's view: judge a script by what it can read on that page, not by its brand
Checks of third-party scripts often end with "it is a big-name service, so it is fine". But the risk OWASP ranks first is the provider's server being compromised, and a widely used service is on many sites, so a compromise there spreads widely.
That is why our Site Transparency Checker never labels a script safe because its provider is famous. The questions that matter are which pages the script runs on, what it can read there, and how many minutes it would take you to switch it off.
Sources (primary)
- OWASP, "Third Party JavaScript Management Cheat Sheet" — cheatsheetseries.owasp.org (the three risks, tag managers, SRI, iframe isolation, in-house mirroring)
- MDN, "Subresource Integrity" — developer.mozilla.org (integrity attribute, allowed hashes, CORS and the crossorigin attribute)
- MDN, "Content Security Policy (CSP)" — developer.mozilla.org (script-src, testing in report-only mode)
- MDN, "CSP: form-action" — developer.mozilla.org (no default-src fallback)
- MDN, "CSP: connect-src" — developer.mozilla.org (the APIs it covers)
- MDN, "Content-Security-Policy-Report-Only" — developer.mozilla.org (needs report-to; not supported in a meta element)
- PCI SSC, "Important Updates Announced for Merchants Validating to Self-Assessment Questionnaire A" (30 January 2025) — blog.pcisecuritystandards.org (requirements 6.4.3 and 11.6.1 effective 31 March 2025)
- MIC (Japan), "External transmission rules" (Japanese) — soumu.go.jp (purpose, scope, what to disclose)
Read next
- Tools: Site Transparency Checker / CSP Builder / Security Headers Checker
- Configuration: Choosing security headers
- Incidents: Polymarket third-party script incident / APORITO online store possible card data leak
- Glossary: What is XSS / What is PCI DSS