Skip to content
fearchitect
Security

Supply Chain Security

Stop malicious npm packages and third-party scripts from owning your app.

By Abas TurabliReviewed

Summary

The average Node project pulls in hundreds of transitive dependencies — any one of which can run arbitrary code at install time, ship malware to users, or exfiltrate secrets via a compromised CDN script. Defense involves lockfiles, `npm ci`, `npm audit`, Subresource Integrity (SRI) on third-party scripts, DOMPurify for sanitization, and minimizing the dependency surface.

Jump to the interview angle

Supply chain security is protecting your app from malicious or compromised code that enters through your dependency tree or third-party scripts — not through your own code.

Three main vectors:

  • Malicious npm packages — typosquatting (e.g., lodahs vs lodash), packages with malicious postinstall scripts, or legitimately-named packages whose maintainer account was hijacked.
  • Compromised CDN scripts — a <script src="https://cdn.example/lib.js"> without an integrity attribute loads whatever the CDN serves, including a modified version after a CDN breach.
  • Transitive drift — a direct dependency adds a new transitive dep with a postinstall hook you never audited.

Core controls

  • Commit `package-lock.json` and run `npm ci` in CI — installs exact locked versions, not ranges.
  • Run `npm audit --audit-level=high` in CI; block merges on high or critical CVEs.
  • Enable Dependabot or Renovate to get automated PRs for dependency version bumps.
  • Add `integrity` + `crossorigin` SRI attributes to every third-party `<script>` and `<link>`.
  • Use DOMPurify before injecting any HTML string from external sources into the DOM.
  • Generate and publish an SBOM (Software Bill of Materials) so consumers can audit your deps.

SRI tag + DOMPurify sanitization

Two concrete patterns: SRI locks a CDN script to a specific hash; DOMPurify strips XSS payloads from untrusted HTML before it reaches innerHTML.

SRI on a CDN link + DOMPurify sanitizetsx
// 1. SRI on a third-party CDN script — in your HTML or Next.js <Script>
// Generate the hash: openssl dgst -sha384 -binary lib.js | openssl base64 -A
// Then paste it as the integrity attribute:
<script
  src="https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.min.js"
  integrity="sha384-<paste the base64 hash from the openssl command above>"
  crossOrigin="anonymous"
/>

// 2. DOMPurify in a React component — sanitize server-provided HTML
import DOMPurify from "dompurify";

interface Props {
  html: string; // raw HTML from an API or CMS
}

export function SafeHtml({ html }: Props) {
  // DOMPurify.sanitize strips script tags, on* handlers, and data: URIs
  const clean = DOMPurify.sanitize(html, { USE_PROFILES: { html: true } });
  // eslint-disable-next-line react/no-danger
  return <div dangerouslySetInnerHTML={{ __html: clean }} />;
}

The integrity attribute makes the browser reject the script if the file has changed. crossOrigin="anonymous" is required or the check is skipped. DOMPurify runs client-side and strips all known XSS vectors.

postinstall scripts run as you

postinstall hooks in any package — direct or transitive — execute with your OS credentials at npm install. A single compromised package can read your SSH keys, .env files, or AWS credentials. Use --ignore-scripts for CI installs of packages you don't trust to run code, and audit new dependencies before adding them.

Interview angle

Interviewers want to know you think about the full code path — not just your code, but every package you pull in and every third-party script you load. Name concrete controls: npm ci, SRI, npm audit, Dependabot, and DOMPurify.

Soundbite: "Lock every dependency, verify every external script hash, and sanitize every HTML string you didn't write."

Key terms

SRI (Subresource Integrity)
Browser check that blocks a `<script>` or `<link>` whose content hash doesn't match the `integrity` attribute.
DOMPurify
JavaScript library that strips XSS vectors from an HTML string before it is inserted into the DOM.
npm ci
Installs exact versions from `package-lock.json`, errors if lock is out of sync — safer than `npm install` in CI.
SBOM (Software Bill of Materials)
Machine-readable inventory of all packages in an application and their versions, used for vulnerability auditing.
Typosquatting
Publishing a malicious npm package whose name resembles a popular package to catch installation typos.

Further reading

Search fearchitect

Jump to a topic, mode, or action.