Caloogy Article
中文

CSP and SRI: Run Only Your Own Code

Date
May 18, 2026
Series
Web Security
Reading
4 min
Topics
WebCspSriXss

The one-sentence version

Any piece of JavaScript in a webpage possesses the same authority as the page itself: it can read forms, modify content, and send requests on your behalf. CSP (Content Security Policy) tells the browser "only run scripts from these specific locations," blocking injected malicious scripts at the door; SRI (Subresource Integrity) tells the browser "the hash of this script must be this specific value," ensuring that if a file on a third-party server is tampered with, it will be rejected. For pages handling money and passwords, the most secure approach is: zero third-party scripts.

This article has three layers:

  1. Layer 1: The Intuition: Why a single external script can destroy a website
  2. Layer 2: Real-World Use: British Airways Magecart, polyfill.io, Ledger Connect Kit
  3. Layer 3: Principles and Engineering details

Layer 1: The Intuition

1.1 External Scripts = Handing Over Your House Keys

Many websites reference third-party code like this:

<script src="https://cdn.some-analytics.com/track.js"></script>

This line of code means: "Fetch a piece of code from that server and run it as me." If that server is compromised, or the domain changes owners, whatever code it returns will be executed on your page, including instructions like "send the user's entered credit card number to me."

1.2 Two Lines of Defense

Defense What it controls Analogy
CSP Which sources of code are allowed to run A security guard only letting employees on a whitelist into the building
SRI What the content of a specific file must be A package with a security seal; if the seal is broken, it is rejected

Layer 2: Real-World Use

Event What happened Which defense could have stopped it
British Airways (2018) Attackers modified a JavaScript library on the BA website, adding 22 lines of code to send payment page card numbers to a fraudulent domain. Approximately 380,000 transactions were affected, resulting in a £20 million fine from UK regulators. CSP's connect-src can prevent data from being sent to unknown domains
polyfill.io (2024) A public script service used by hundreds of thousands of websites had its domain sold, after which it began serving malicious redirect code to some visitors. SRI would prevent the tampered file from executing; more thoroughly, one should avoid referencing external CDNs entirely
Ledger Connect Kit (2023) Attackers used phishing to obtain a former employee's npm account and published a new version containing a "token stealer"; many DeFi frontends automatically loaded the latest version via CDN, resulting in user losses of approximately $600,000 within hours. Lock versions + SRI, or bundle dependencies into your own code

This category of attack is collectively known as Magecart (web skimming) or supply chain attacks: the attacker does not touch your server, but instead modifies the third-party code you trust.


Layer 3: Principles and Engineering

3.1 A Strict CSP

Content-Security-Policy:
  default-src 'none';
  script-src 'self';
  style-src 'self';
  img-src 'self' data:;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';
  base-uri 'none';
  form-action 'self';
  report-to csp-endpoint
Directive Meaning
default-src 'none' Deny everything by default, then allow specific items below
script-src 'self' Only run script files from this site; inline scripts and eval are strictly prohibited, which is key to blocking most XSS
connect-src The page can only send fetch / WebSocket to these addresses; even if malicious scripts sneak in, they cannot steal data
frame-ancestors 'none' Cannot be embedded in an iframe, preventing clickjacking
base-uri 'none' Prevents injecting <base> tags that could tamper with all relative links
form-action 'self' Forms can only be submitted to this site
report-to The browser automatically reports violations; this can be used as an intrusion alert

Before going live, you can use Content-Security-Policy-Report-Only to report without blocking, observe for a period, and only enable it officially once you have confirmed there are no false positives.

3.2 Writing SRI

<script src="https://cdn.example.net/lib-4.2.1.min.js"
        integrity="sha384-(SHA-384 hash of file contents, base64 encoded)"
        crossorigin="anonymous"></script>

After the browser downloads a file, it calculates the hash; if it doesn't match, execution is refused. It relies on the second pre-image resistance property of hash functions: an attacker cannot create a malicious file with different content but the same hash (see "The Birthday Paradox and Hash Collisions").

Limitations: SRI can only be used for fixed-version files. If you reference an "always latest version" URL, the content will change, the hash will change, and SRI will not work. This "always latest version" approach was precisely the root cause of the Ledger Connect Kit incident.

3.3 Zero Third-Party Scripts

For pages involving signatures, payments, or logins, the most secure approach is:

  1. All dependencies must lock versions and be bundled into your own code during build time, rather than being loaded from any CDN at runtime;
  2. Do not include any third-party scripts such as analytics, advertising, or customer chat;
  3. Dependency upgrades should follow a manual review process; do not enable automatic merging;
  4. Note that the hosting platform itself may inject things into the page (analytics, performance optimization, email obfuscation scripts); these need to be disabled, or you must use Cache-Control: no-transform and perform regular inspections (see "The Bybit Incident and Frontend Integrity").

3.4 What CSP Cannot Prevent

These two scenarios must be defended against through deployment pipeline security and online integrity inspections.


Summary

Layer Key points
Intuition External scripts run as you, which is equivalent to handing over your house keys
CSP Limits code sources and data destinations; bans inline scripts and eval; use violation reporting as alerts
SRI Uses hashes to "seal" files; only applicable to fixed versions
Best Practice Zero third-party scripts for sensitive pages; lock dependency versions, bundle them, and use manual reviews