diff --git a/docs/pages/front-end-web-app/index.mdx b/docs/pages/front-end-web-app/index.mdx index 7a2fe11e..4ab594cc 100644 --- a/docs/pages/front-end-web-app/index.mdx +++ b/docs/pages/front-end-web-app/index.mdx @@ -13,6 +13,7 @@ title: "Front End Web App" - [Front-End Web Application Security](/front-end-web-app/overview) - [Web Application Security](/front-end-web-app/web-application-security) +- [Third-Party Script Security](/front-end-web-app/third-party-script-security) - [Mobile Application Security](/front-end-web-app/mobile-application-security) - [Common Web Vulnerabilities](/front-end-web-app/common-vulnerabilities) - [Security Tools & Resources](/front-end-web-app/security-tools-resources) diff --git a/docs/pages/front-end-web-app/overview.mdx b/docs/pages/front-end-web-app/overview.mdx index d3d2f130..c7770fdf 100644 --- a/docs/pages/front-end-web-app/overview.mdx +++ b/docs/pages/front-end-web-app/overview.mdx @@ -25,8 +25,9 @@ as they could, for example, start interacting with a malicious contract instead 1. [Web Application Security](/front-end-web-app/web-application-security) 2. [Mobile Application Security](/front-end-web-app/mobile-application-security) -3. [Common Vulnerabilities](/front-end-web-app/common-vulnerabilities) -4. [Security Tools and Resources](/front-end-web-app/security-tools-resources) +3. [Third-Party Script Security](/front-end-web-app/third-party-script-security) +4. [Common Vulnerabilities](/front-end-web-app/common-vulnerabilities) +5. [Security Tools and Resources](/front-end-web-app/security-tools-resources) --- diff --git a/docs/pages/front-end-web-app/third-party-script-security.mdx b/docs/pages/front-end-web-app/third-party-script-security.mdx new file mode 100644 index 00000000..c1eb0c8a --- /dev/null +++ b/docs/pages/front-end-web-app/third-party-script-security.mdx @@ -0,0 +1,388 @@ +--- +title: "Third-Party Script Security | SEAL" +description: "Safely load third-party scripts in Web3 frontends using Content Security Policy (CSP) and Subresource Integrity (SRI). Prevent supply chain attacks on Web3 users." +tags: + - Engineer/Developer + - Security Specialist +contributors: + - role: wrote + users: [scode2277] +--- + +import { TagList, AttributionList, TagProvider, TagFilter, ContributeFooter } from '../../../components' + + + + +# Third-Party Script Security + + + + +> 🔑 **Key Takeaway:** Every third-party script running on your frontend shares your page's origin, meaning it +> can access cookies, localStorage, session tokens, and call `window.ethereum` methods directly. Use Content +> Security Policy, Subresource Integrity, and Trusted Types to control what code executes, verify it has not +> been tampered with, and lock down dangerous DOM APIs. + +Web3 frontends are high-value targets because they sit between users and their wallets. Every script that runs +on your page executes with the same permissions as your own code. When a user visits your application and signs +a transaction, any script on the page can observe, modify, or replace that interaction. If an attacker +compromises a third-party script your frontend loads (a CDN-hosted library, an analytics snippet, a wallet +connector), they can silently redirect transactions, drain wallets, or harvest credentials without touching your +own code. + +This is not a theoretical concern. Multiple attacks have exploited third-party scripts to compromise +Web3 frontends at scale (see [Past Incidents](#past-incidents) below). Three browser-native +mechanisms, **Content Security Policy (CSP)**, **Subresource Integrity (SRI)**, and **Trusted Types**, provide +strong defenses against these attacks. Neither requires external tooling or dependencies because they are built +into every modern browser. + +## Content Security Policy (CSP) + +A Content Security Policy is an HTTP response header that tells the browser which sources of content are +permitted to load on your page. If a script, style, image, or connection does not match your policy, the browser +blocks it. This means that even if an attacker injects a ` +``` + +### How It Works + +1. You generate a SHA-256, SHA-384, or SHA-512 hash of the exact file you expect to load. +2. You include this hash in the `integrity` attribute of the ` +``` + +With this import map in place, any code that runs `import('ethers')` will resolve to your self-hosted copy, not +to an external CDN. Combined with a CSP that restricts `script-src` to your own origin (or uses +`strict-dynamic`), this gives you centralized control over module resolution even for dynamic imports. + +Import maps do not replace SRI. They address a different part of the problem: SRI verifies file integrity; +import maps control where files are loaded from. Use them together: import maps to pin resolution to known +locations, and SRI on any statically loaded scripts from those locations. + +## Trusted Types + +Trusted Types is a browser API (enforced via CSP) that prevents DOM-based cross-site scripting by locking down +dangerous sink APIs. Functions like `innerHTML`, `outerHTML`, `document.write`, `eval`, and `setTimeout(string)` +are the most common vectors for DOM XSS. Trusted Types makes it impossible to pass raw strings to these sinks. +You must instead pass a "trusted" value created through a policy you define. + +For Web3 frontends, this is directly relevant. Wallet connection flows, transaction confirmation UIs, and token +approval dialogs often manipulate the DOM. If an attacker can inject markup through a compromised dependency +that uses `innerHTML`, they can render a fake approval dialog or redirect a transaction. Trusted Types block +this class of attack at the API level. + +### Enabling Trusted Types + +Add `require-trusted-types-for 'script'` to your CSP header: + +``` +Content-Security-Policy: + require-trusted-types-for 'script'; + trusted-types myapp-policy; +``` + +Then define a named policy in your application code. At minimum the policy should sanitize HTML input before +it reaches the DOM (using a library like DOMPurify), block dynamic script creation, and restrict script URLs +to your own origin. The [MDN Trusted Types documentation](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API) and +the [Google adoption guide](https://web.dev/articles/trusted-types) cover policy implementation in detail. + +### Adoption Strategy + +Trusted Types can be disruptive to adopt because many libraries (including some wallet connectors) use +`innerHTML` internally. Roll it out gradually: + +1. **Start in report-only mode** using `Content-Security-Policy-Report-Only` with + `require-trusted-types-for 'script'`. This logs violations without breaking anything. +2. **Identify violating code** from the reports. Common culprits are UI libraries, rich text rendering, and + third-party widgets. +3. **Create a `default` policy** as a transitional measure. The browser calls it for any assignment that does + not already use a trusted type, letting you handle violations centrally before enforcing per-policy. +4. **Enforce** once violations are resolved. + +Trusted Types are supported across all modern browsers as of early 2026. The CSP directive degrades gracefully +on older browsers: it is simply ignored, so it will not break your application. + +## Self-Hosting Critical Dependencies + +The strongest defense against third-party script compromise is to eliminate the third party entirely by +bundling dependencies into your own build output. CSP and SRI reduce the risk of loading external scripts; +self-hosting removes it. For guidance on vendoring, version pinning, and managing the operational trade-offs, +see [Dependency Awareness](/supply-chain/dependency-awareness). + +## Past Incidents + +These attacks demonstrate why third-party script controls are not optional for Web3 frontends: + +- **npm registry attack (September 2025).** A maintainer's credentials were phished and malicious versions of + 18 widely-used packages, including `chalk`, `debug`, and `ansi-styles`, were published. The payload hooked + `window.ethereum` to intercept wallet calls and rewrote `fetch`/`XMLHttpRequest` to reroute transactions to + attacker-controlled addresses. SRI would have blocked the tampered scripts; a strict `connect-src` policy + would have prevented exfiltration. +- **Lottie Player (October 2024).** Malicious versions of `@lottiefiles/lottie-player` were published, + injecting a crypto drainer into any site displaying Lottie animations. The payload prompted users to connect + their wallets and drained funds. Applications loading the library via CDN without SRI were immediately + vulnerable. +- **Polyfill.io (June 2024).** After a change in ownership, the `polyfill.io` CDN began injecting malicious + redirects into a script served to over 100,000 websites, targeting mobile users. Sites using SRI would have + blocked the modified script entirely. +- **Ledger Connect Kit (December 2023).** A former employee's npm credentials were used to publish a malicious + version of `@ledgerhq/connect-kit`. The injected code rendered a fake wallet connection modal that redirected + funds. Every application loading the library without integrity checks was affected simultaneously. + +For a broader catalog of supply chain attack vectors, see [Web3 Supply Chain Threats](/supply-chain/web3-supply-chain-threats). + +## Runtime Monitoring + +Build-time defenses (CSP, SRI, self-hosting) establish the baseline, but you also need visibility into what +happens at runtime in production. Attacks do not always come through the vectors you anticipated, and +misconfigurations can silently weaken your defenses. + +### CSP Violation Reporting + +Start every new policy in report-only mode using `Content-Security-Policy-Report-Only`. This logs what would +be blocked without breaking anything. Review the reports, adjust the policy, and only switch to the enforcing +`Content-Security-Policy` header once you are confident it will not break legitimate functionality. After +switching to enforcement, keep `report-to` configured so any new violations surface immediately. + +Set `report-to` in your CSP header and pair it with a `Report-To` header that points to a collection endpoint +you control. Every blocked resource generates a report containing the violated directive, the blocked URI, and +the page where it happened. Aggregate these to detect injection attempts, misconfigurations after deployments, +and third-party scripts loading unexpected resources. + +### DOM Mutation Monitoring + +CSP cannot detect all forms of script injection, particularly when a trusted script's behavior changes (for +example, a compromised dependency that starts injecting iframes or modifying wallet-related DOM elements). +MutationObservers let you watch for suspicious changes at runtime: flag any script node added without a nonce, +and remove unexpected iframes that were not part of your known page structure. + +This is not a replacement for CSP. It is a detection layer. Use it to catch things that slip through policy +gaps or to monitor for unexpected behavior from trusted scripts. + +### External Script Change Detection + +For any script you load from a third-party origin (even with SRI), run a periodic job that fetches the resource +and compares its hash to the expected value. A hash mismatch on a resource that should not have changed is an +early indicator of a supply chain compromise. Integrate this into your CI pipeline and your production monitoring +separately: CI catches changes at build time, production monitoring catches changes at serve time. + +## Additional Defenses + +Beyond the core mechanisms above, consider these complementary measures: + +- **Iframe sandboxing for third-party widgets.** If you must embed third-party content, load it in sandboxed + iframes with restrictive `sandbox` attributes. This isolates it from your main page context and prevents it + from interacting with wallet-related DOM or JavaScript. +- **Permissions Policy.** The `Permissions-Policy` HTTP header restricts which browser features third-party + scripts and frames can access: payment APIs, clipboard, camera, and others. Even if a compromised script + runs, it cannot invoke features your application never needed. + +## Further Reading + +- [MDN: Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) -> API reference and browser compatibility +- [MDN: Securing CDN resources with SRI](https://developer.mozilla.org/en-US/blog/securing-cdn-using-sri-why-how/) -> walkthrough on applying SRI to CDN-hosted assets +- [MDN: Import Maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) -> specification and usage guide +- [MDN: Trusted Types](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API) -> API reference and browser compatibility +- [Google: Trusted Types Adoption Guide](https://web.dev/articles/trusted-types) -> step-by-step policy implementation guide + +## Related Frameworks + +- [Supply Chain Security](/supply-chain/overview): Dependency management, vendor risk, and incident response + for compromised components +- [Web3 Supply Chain Threats](/supply-chain/web3-supply-chain-threats): Catalog of frontend, smart contract, + and infrastructure attack vectors +- [Dependency Awareness](/supply-chain/dependency-awareness): Version pinning, lockfile integrity, and + vulnerability scanning for the packages your frontend loads +- [DevSecOps](/devsecops/overview): Integrating security checks into your build and deployment pipelines +- [Domain & DNS Security](/infrastructure/domain-and-dns-security/overview): Preventing DNS hijacking and CDN + cache poisoning + +--- + + + diff --git a/docs/pages/supply-chain/dependency-awareness.mdx b/docs/pages/supply-chain/dependency-awareness.mdx index 1780714b..2026934c 100644 --- a/docs/pages/supply-chain/dependency-awareness.mdx +++ b/docs/pages/supply-chain/dependency-awareness.mdx @@ -381,6 +381,8 @@ contracts and their imported libraries, see - [Snyk Vulnerability Database](https://security.snyk.io/): Searchable database of known vulnerabilities - [Cargo Security Advisories](https://rustsec.org/): Rust security advisory database and `cargo-audit` - [Go Vulnerability Database](https://vuln.go.dev/): Official Go vulnerability tracking and `govulncheck` +- [Third-Party Script Security](/front-end-web-app/third-party-script-security): Runtime integrity controls (Content + Security Policy, Subresource Integrity, self-hosting) that complement build-time dependency practices --- diff --git a/docs/pages/supply-chain/web3-supply-chain-threats.mdx b/docs/pages/supply-chain/web3-supply-chain-threats.mdx index 032959ad..7c0105d7 100644 --- a/docs/pages/supply-chain/web3-supply-chain-threats.mdx +++ b/docs/pages/supply-chain/web3-supply-chain-threats.mdx @@ -56,6 +56,9 @@ the user's browser. For practices to defend against these attacks, see [Dependency Awareness](/supply-chain/dependency-awareness). +For runtime integrity verification using Subresource Integrity and Content Security Policy, see +[Third-Party Script Security](/front-end-web-app/third-party-script-security). + ### Wallet Connector Library Hijacking Wallet connector libraries are a particularly high-value target because they sit at the exact point where user intent @@ -69,6 +72,9 @@ meets transaction construction. For wallet-specific security practices, see the [Wallet Security](/wallet-security/overview) framework. +For browser-level controls that would have blocked execution of the tampered library, see +[Third-Party Script Security](/front-end-web-app/third-party-script-security). + ### CDN and Hosting Compromise An attacker who compromises your hosting provider or poisons a CDN cache can serve tampered JavaScript to all users @@ -78,8 +84,10 @@ without touching your repository. signing with fund redirection. - **CDN cache poisoning** can serve malicious scripts even if your origin server is clean. -For DNS hardening, registrar locks, and monitoring, see the -[Domain & DNS Security](/infrastructure/domain-and-dns-security/overview) framework. +For DNS hardening, registrar locks, and monitoring, see the [Domain & DNS Security](/infrastructure/domain-and-dns-security/overview) framework. + +For browser-level defenses against CDN and hosting compromise, including Content Security Policy, Subresource Integrity, and self-hosting +strategies, see [Third-Party Script Security](/front-end-web-app/third-party-script-security). ## Smart Contract Dependency Risks @@ -252,6 +260,8 @@ For hardware wallet security guidance, see the [Wallet Security](/wallet-securit [Vendor Risk Management](/supply-chain/vendor-risk-management) guide - Track real-time exploit data and historical incidents on the [DeFiLlama Hacks Dashboard](https://defillama.com/hacks) +- [Third-Party Script Security](/front-end-web-app/third-party-script-security): Runtime integrity controls (Content + Security Policy, Subresource Integrity, self-hosting) that complement build-time dependency practices --- diff --git a/utils/fetched-tags.json b/utils/fetched-tags.json index 94e7693b..dd51ac91 100644 --- a/utils/fetched-tags.json +++ b/utils/fetched-tags.json @@ -413,6 +413,10 @@ "Engineer/Developer", "Security Specialist" ], + "/front-end-web-app/third-party-script-security": [ + "Engineer/Developer", + "Security Specialist" + ], "/front-end-web-app/web-application-security": [ "Engineer/Developer", "Security Specialist" diff --git a/vocs.config.tsx b/vocs.config.tsx index 55576c95..438e9aa7 100644 --- a/vocs.config.tsx +++ b/vocs.config.tsx @@ -175,6 +175,7 @@ const config = { items: [ { text: 'Overview', link: '/front-end-web-app/overview', dev: true }, { text: 'Web Application Security', link: '/front-end-web-app/web-application-security', dev: true }, + { text: 'Third-Party Script Security', link: '/front-end-web-app/third-party-script-security', dev: true }, { text: 'Mobile Application Security', link: '/front-end-web-app/mobile-application-security', dev: true }, { text: 'Common Vulnerabilities', link: '/front-end-web-app/common-vulnerabilities', dev: true }, { text: 'Security Tools and Resources', link: '/front-end-web-app/security-tools-resources', dev: true },