Apr 14, 2019
The Dangers of Piggybacking Scripts
Why piggybacking on third-party scripts can introduce security risks, performance problems, and unexpected breakages in your application.
It’s tempting to load a third-party script — analytics, chat widgets, ad trackers — into your application and call it a day. But every script you include runs with the same privileges as your own code. That convenience comes with real risks.
Supply Chain Attacks
When you include a script from a third-party CDN or domain, you’re trusting that:
- The provider won’t go malicious. A compromised or hostile script vendor can inject keyloggers, steal cookies, or exfiltrate user data.
- The provider won’t be breached. If their CDN is compromised, every site loading that script is affected.
- The script won’t be removed. When a script disappears, your application breaks — or worse, a different script can be served at the same URL.
The Zach Edwards tweet thread highlighted how scripts loaded from third parties can collect far more data than their stated purpose, often sending it to additional endpoints without the site owner’s knowledge.
Data Exfiltration
A third-party script can access anything your page can access:
- Cookies — including session tokens if they’re not marked
HttpOnly - DOM content — personal data, form inputs, payment information
- URL parameters — tracking IDs, referral codes, authentication tokens
- JavaScript globals — any object or function exposed in the window scope
Even well-intentioned scripts often send data to more endpoints than you’d expect. Check the network tab in your browser’s dev tools — you may be surprised.
Performance Impact
Each additional script adds:
- Network latency — DNS lookups, TLS handshakes, and downloads for each domain
- Parse and execute time — JavaScript blocks the main thread during parsing
- Memory overhead — each script allocates objects, listeners, and timers that persist
A page with 10 third-party scripts can spend more time executing those scripts than running its own application code.
Mitigation Strategies
Use Subresource Integrity (SRI)
SRI lets you pin a script to a specific hash, preventing a compromised server from serving a different file:
<script
src="https://cdn.example.com/analytics.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx5HN3NBLxU9k1x5Y5f3"
crossorigin="anonymous">
</script>
If the file changes, the browser will refuse to execute it.
Use Content Security Policy (CSP)
A strict CSP limits which scripts can run on your page:
Content-Security-Policy: script-src 'self' https://cdn.example.com;
This prevents inline scripts, eval(), and unauthorized script sources — even if an attacker finds an injection point.
Audit What You Load
Regularly review the scripts you include:
- Do you still need it? Remove anything that’s no longer providing value.
- What domains does it contact? Use dev tools or a tool like Requestly to monitor outbound requests.
- Is it reputable? Prefer widely-used, actively-maintained libraries from trusted sources.
Self-Host When Possible
Instead of loading from a third-party CDN, download the script and serve it from your own infrastructure:
<!-- Instead of this: -->
<script src="https://cdn.example.com/analytics.js"></script>
<!-- Serve this: -->
<script src="/js/analytics.js" integrity="sha384-..."></script>
You gain full control over the file, eliminate the third-party domain dependency, and can still use SRI for tamper protection.
Sandbox with iframes
For scripts that must remain third-party, isolate them in a sandboxed iframe:
<iframe
sandbox="allow-scripts"
src="https://widget.example.com/embed">
</iframe>
The sandbox attribute restricts the iframe’s capabilities — it can’t access your cookies, DOM, or storage.
The Bottom Line
Every script you add to your page is a bet on someone else’s security, reliability, and intentions. Before you include that next third-party script, ask:
- What data does it access?
- Where does it send data?
- What happens if it goes down?
- What happens if it’s compromised?
If you can’t answer those questions, the script doesn’t belong in your application.