Anay Pandya
Founder of ZeriFlow · 10 years fullstack engineering · About the author
Key Takeaways
- Supply chain attacks compromise your website through trusted third-party code. Learn how to defend against malicious npm packages, CDN tampering, and GitHub Actions exploits.
- Includes copy-paste code examples and step-by-step instructions.
- Free automated scan available to verify your implementation.
Supply Chain Attack Prevention: Protect Your Website from Compromised Dependencies
Supply chain attacks have become one of the most dangerous vectors in web security precisely because they exploit trust. When a malicious actor compromises a dependency your website relies on — an npm package, a CDN-hosted script, a GitHub Action — they inherit all the trust you've extended to that component. Your defenses don't trigger because, from your infrastructure's perspective, the code is coming from a legitimate source.
<div class="zf-stat-callout" style="background:#0d1117;border:1px solid rgba(16,185,129,0.25);border-left:3px solid #10b981;border-radius:4px;padding:16px 20px;margin:24px 0"> <p style="margin:0 0 4px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.15em;color:#10b981;font-family:monospace">ZeriFlow Data — 12,400+ sites analyzed</p> <p style="margin:0;font-size:13px;color:#e2e8f0;line-height:1.6;font-family:monospace">In ZeriFlow's dataset of 12,400+ scanned sites, the average security score is 52/100 — with 68% failing at least one critical check in categories including TLS configuration, check your security headers, DNS authentication, and cookie handling.</p> </div>
Is your site actually secure?
Run a free check — 60 seconds
Is your site exposed? Run a free ZeriFlow scan →
What Is a Software Supply Chain Attack?
A supply chain attack targets the tools, libraries, and services that feed into your software rather than your application directly. Instead of exploiting a vulnerability in your code, attackers compromise something you depend on. The 2020 SolarWinds attack is the most famous example at the enterprise level, but the web ecosystem — npm, PyPI, CDNs, GitHub — has its own persistent supply chain threat.
For website owners and developers, the threat materializes in three main ways: compromised package registry packages, poisoned CDN resources, and malicious CI/CD pipeline actions.
Type 1: Malicious npm and Open-Source Packages
The npm ecosystem hosts over 2 million packages. Attackers exploit this scale through several techniques:
Typosquatting — publishing packages with names similar to popular ones. crossenv (not cross-env), lodash clones, event-stream variants. Developers mistype a package name during npm install and pull down malware.
Dependency confusion — if your organization uses private npm packages with certain names, attackers can publish public packages with the same names at higher version numbers. npm resolves the public version, pulling attacker code into your build.
Account takeover — if a popular package maintainer's npm account is compromised (weak password, no MFA), the attacker publishes a new "update" with malicious code to all existing users. This is how the event-stream incident in 2018 worked, affecting millions of projects.
Abandoned package hijack — an attacker takes over maintenance of an unmaintained package and publishes a malicious update. Popular packages with millions of weekly downloads have been abandoned and later re-registered by malicious actors.
Mitigation:
- Use lock files (package-lock.json, yarn.lock) and commit them to version control. They pin exact versions and hashes.
- Enable npm audit in your CI pipeline and fail builds on high-severity findings.
- Use npm install --ignore-scripts to prevent postinstall scripts from executing arbitrary code on install.
- Scope private packages properly and configure your registry to prevent dependency confusion.
Type 2: CDN and Third-Party Script Compromise
Many websites load JavaScript from third-party CDNs: analytics, A/B testing, payment widgets, chat tools, ad networks. If any of those CDNs is compromised — or if you're loading a file that can be updated by a third party without your knowledge — attackers can inject malicious code that runs in every visitor's browser.
The British Airways formjacking attack (2018) is a textbook example: attackers injected 22 lines of JavaScript into a third-party script loaded by the payment page. Over 400,000 customers had their payment details exfiltrated. The script had been loading from a CDN with no integrity verification.
Subresource Integrity (SRI) is the direct defense. When you include an external script with an SRI hash, the browser verifies the file's content against the hash before executing it:
<script
src="https://cdn.example.com/library.min.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous">
</script>If the file's content changes — even by a single byte — the browser refuses to execute it. The attack is neutralized before it runs.
ZeriFlow checks whether external scripts on your pages include valid SRI hashes, and whether your CSP header reinforces this policy.
Check your SRI and CSP configuration →
Type 3: GitHub Actions and CI/CD Pipeline Poisoning
GitHub Actions workflows are increasingly targeted. Common attack patterns:
Malicious third-party actions — uses: some-org/some-action@v1 pins a version tag, but tags in git can be force-pushed. If v1 is updated to point to a malicious commit, your workflow runs attacker code with access to your secrets.
Pull request poisoning — for public repositories, attackers open PRs that modify workflow files, hoping maintainers merge without scrutinizing the YAML changes.
Self-hosted runner compromise — self-hosted runners with insufficient isolation can be exploited by malicious PRs to access internal network resources or exfiltrate secrets.
Mitigation:
- Pin Actions by commit SHA, not tag: uses: actions/checkout@a81bbbf8298c0fa03ea29cdc473d45769f953675
- Use tools like Renovate or Dependabot to receive PRs when pinned SHA commits update.
- Restrict GITHUB_TOKEN permissions to the minimum required (permissions: read-all by default, explicit write grants only where needed).
- Never pass secrets to workflows triggered by pull_request from forks.
Content Security Policy as a Last Line of Defense
Even if a supply chain compromise occurs, a properly configured Content Security Policy (CSP) limits what the injected script can do:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com; connect-src 'self' https://api.yoursite.comWith this policy in place:
- Scripts from any domain not in script-src are blocked from executing.
- XHR/fetch requests to domains not in connect-src are blocked — preventing data exfiltration.
- Inline scripts are blocked by default, neutralizing many injection attacks.
CSP doesn't prevent compromise of a trusted CDN, but it limits attacker capability to the permitted origins and connection targets — significantly constraining what they can steal or do.
Pair CSP with SRI hashes for external scripts, and you've created a configuration where even a compromised trusted CDN can't execute modified code.
Additional Supply Chain Controls
Software Bill of Materials (SBOM)
Generate and maintain a Software Bill of Materials — a machine-readable inventory of every component in your application. Tools like Syft (for containers), CycloneDX, and SPDX produce SBOMs that you can scan against vulnerability databases automatically.
GitHub now supports SBOM export directly from the dependency graph. Knowing what you depend on is a prerequisite for knowing when something goes wrong.
Dependency Review in Pull Requests
GitHub's dependency-review-action automatically comments on PRs that introduce packages with known vulnerabilities or license changes. Integrate it into your workflow:
- name: Dependency Review
uses: actions/dependency-review-action@v3Runtime Application Self-Protection (RASP)
For high-security applications, RASP tools instrument your running application to detect and block anomalous behavior — like a dependency that suddenly tries to read /etc/passwd or make an outbound connection to an unknown IP.
Supply Chain Security Checklist
- [ ] Lock files committed and verified in CI (
npm cinotnpm install) - [ ]
npm auditruns in CI pipeline with high-severity failure - [ ] All external CDN scripts include SRI hashes
- [ ] CSP header restricts
script-srcandconnect-src - [ ] GitHub Actions pinned to commit SHAs
- [ ] Dependabot or Renovate configured for automated dependency updates
- [ ] SBOM generated and scanned for known CVEs
- [ ] MFA enabled on all package registry accounts (npm, PyPI)
FAQ
Q: How common are npm supply chain attacks?
A: Increasingly common. The Socket research team reports hundreds of malicious packages published to npm monthly. Most are caught quickly, but the window between publication and removal is enough for automated CI pipelines to pull them in.
Q: Does SRI work for <link> stylesheets too?
A: Yes. The integrity attribute works for both <script> and <link rel="stylesheet"> tags. It's equally important to apply it to CSS loaded from third-party CDNs, as malicious CSS can exfiltrate form data using CSS attribute selectors.
Q: What if I'm using a CDN and can't predict the hash?
A: For dynamically updated CDN resources where you need the latest version, use your CDN's feature to lock a specific version, then generate and update the SRI hash as part of your deployment pipeline. Tools like sri-toolbox automate this.
Q: Can Subresource Integrity prevent the formjacking attack on British Airways?
A: Yes, precisely. The modified script would have had a different hash than the one declared in the integrity attribute, and the browser would have refused to execute it. SRI is the direct mitigation for CDN-based formjacking.
Q: Does ZeriFlow check for SRI on external scripts?
A: ZeriFlow checks your CSP header configuration, which is the policy layer that enforces SRI requirements. A CSP with require-sri-for script directive, combined with ZeriFlow's header audit, gives you a comprehensive view of your supply chain attack surface.
Conclusion
Supply chain attacks are effective because they bypass your perimeter by hiding inside trusted code. Defending against them requires locking down your dependency management, implementing SRI for all external scripts, and using CSP to contain the blast radius of any compromise that does occur. These are not complex changes — most are configuration adjustments that take under an hour to implement.
Scan your site free on ZeriFlow →
Further Reading
<!-- zf-internal-links -->
Runtime Application Self-Protection
Beyond build-time controls, consider Runtime Application Self-Protection (RASP) for high-risk applications. RASP agents instrument your running application and can detect and block exploitation attempts in real time — including attempts to load unexpected third-party scripts injected via a compromised dependency.
For frontend applications, a strict Content-Security-Policy is the browser-native equivalent: it prevents unauthorized scripts from executing even if they reach your bundle. Combine a CSP nonce-based policy with your SRI integrity checks for defense in depth.
Monitoring Dependencies Continuously
Supply chain security is not a one-time fix — new vulnerabilities are disclosed daily in packages you already depend on.
Set up automated monitoring:
# .github/workflows/dependency-review.yml
name: Dependency Review
on: [pull_request]
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/dependency-review-action@v4
with:
fail-on-severity: moderateFor npm projects, enable automated security updates:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10Dependabot and Renovate Bot both open pull requests automatically when new versions of your dependencies are available, including patch releases that address security vulnerabilities. Merging security patches promptly is the single most effective operational control against known-vulnerability exploitation.
Verifying Your Supply Chain Security Posture
After implementing lock files, SRI, and dependency auditing, verify your deployed application's security headers and CSP configuration with a ZeriFlow scan. A strong Content-Security-Policy that blocks unknown script sources is your last line of defense if a dependency is compromised after deployment — it prevents the malicious code from loading even if it reaches your bundle.
ZeriFlow evaluates your CSP directive quality, checking for unsafe-inline, unsafe-eval, and wildcard source directives that would neutralize your policy. A supply chain attack that injects a malicious script into your bundle cannot execute in a browser enforcing a properly scoped CSP — making header quality an integral part of your supply chain defense strategy.
Related resources
Keep improving your website security
Related tools
Website Vulnerability Scanner
Run a broader website security audit across headers, TLS, DNS, cookies, SEO, and disclosure checks.
Security Headers Checker
Check CSP, HSTS, X-Frame-Options, and other response headers.
SSL Checker
Review TLS certificate, HTTPS, and transport security signals.
DMARC Checker
Validate email authentication records for domain spoofing protection.
CSP Checker
Review Content-Security-Policy coverage and common gaps.