← Back to Blog

The Outdated JavaScript Problem: Why Old Libraries Are the Most Common Unpatched Hole on the Web

The Outdated JavaScript Problem: Why Old Libraries Are the Most Common Unpatched Hole on the Web

Part of the security audit tool stack. See the pillar post for the full catalog of sibling audits and where this one fits.

Most "we got hacked" stories on small sites don't start with a clever zero-day. They start with a library that was three years out of date. The site was running jQuery 3.3, or a Bootstrap from 2018, or a copy of Moment.js that nobody has touched since launch. Each of those carries a published CVE — a public, numbered, documented bug with proof-of-concept code already on GitHub. No exploit research required. An attacker scans for the version string, matches it to the CVE, and runs the payload.

This is the most common real vulnerability on the small-business web, and it's also the most boring to fix: you upgrade the library. The hard part has always been knowing which of the libraries on your page are out of date, and by how much. That's the gap the Mega Security Analyzer now closes with its dependency-and-framework version layer.

Why "old" equals "exploitable"

A version number on a front-end library is not cosmetic. It's a precise statement of which known bugs are present. A few examples that the analyzer flags by default:

  • jQuery below 3.5.0 is vulnerable to cross-site scripting via CVE-2020-11022 and CVE-2020-11023. jQuery is on a huge share of the web, so this is the single most common finding.
  • Bootstrap below 4.3.1 (and the entire 3.x line below 3.4.1) carries XSS through data attributes — CVE-2019-8331 and the 2018 pair CVE-2018-14041/CVE-2018-14042.
  • Lodash below 4.17.21 has both a command-injection (CVE-2021-23337) and a prototype-pollution (CVE-2020-8203) bug.
  • Handlebars below 4.7.7 allows prototype pollution that can escalate to remote code execution (CVE-2021-23369).
  • AngularJSany 1.x version — is end-of-life as of January 2022. It will never be patched again, and it has open CVEs. Running it at all is the finding.
  • Moment.js isn't end-of-life, but it's in permanent legacy/maintenance mode, and versions below 2.29.4 have a ReDoS (CVE-2022-31129) and a path-traversal (CVE-2022-24785) bug.

The pattern is always the same: the maintainers fixed the bug in a specific release, and everything below that release is a documented target.

How the analyzer finds your versions

You can't fix what you can't see. The version layer detects libraries three ways, all from a single fetch of your page — no install on your server, nothing run in your browser:

  1. CDN URL fingerprints. Most sites load libraries from a CDN with the version baked into the path: cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/..., cdn.jsdelivr.net/npm/bootstrap@4.3.1/..., unpkg.com/vue@2.6.14/..., code.jquery.com/jquery-3.5.1.min.js. The analyzer parses the name and version out of every script and stylesheet URL. It also reads the WordPress convention of jquery.min.js?ver=3.7.1, where the ?ver query string carries the real library version — which is how it catches outdated jQuery on the millions of WordPress sites that ship it that way.
  2. License banners. Minified library files keep a header comment — /*! jQuery v3.5.1 |..., Bootstrap v5.3.3, moment.js version : 2.29.1. When a library is self-hosted with no version in the filename, the banner still gives it away.
  3. Exposed dependency manifests. If a package.json or composer.json is reachable at your web root (it shouldn't be — that's its own finding), the analyzer reads the declared dependency ranges and flags any that permit a known-vulnerable release. This is where build-time-only packages like glob, minimatch, semver, and lodash show up.

Each detected library is compared against a dated baseline of the current latest stable version and the security floor — the lowest version with no known high or critical CVE. You get one of three verdicts per library: current (green), outdated-but-no-known-critical-bug (amber), or below the security floor / end-of-life (red, with the CVE numbers attached).

How to correct your site

The fix is almost always one of four moves:

  1. Upgrade in place. If you load from a CDN, change the version in the URL to the current release and test. Most minor and patch upgrades are drop-in. Major upgrades (jQuery 1.x → 3.x, Bootstrap 4 → 5, Vue 2 → 3) need a migration pass — read the library's upgrade guide first.
  2. Self-host the current version with Subresource Integrity. Download the latest file, serve it from your own /js/, and add an integrity="sha384-..." hash to the <script> tag. This removes the third-party CDN as a single point of failure and pins the exact bytes you reviewed. (See the Remote Dependency Audit for the self-hosting walkthrough.)
  3. Remove what you no longer use. A surprising amount of jQuery on the modern web is loaded for one plugin that could be ten lines of vanilla JavaScript. If a library is end-of-life (AngularJS 1.x, MooTools, Prototype.js, the old jQuery carousel plugins), the only durable fix is to replace it.
  4. Lock down the manifest leak. If the scan read your package.json off the live site, move it out of the published directory. Build artifacts belong in the build step, not the web root.

The analyzer's AI fix prompt bundles all of this — every outdated library, its current target version, the CVE it closes, and a migration note — into a single paste-into-Claude-or-ChatGPT prompt so you get a per-library upgrade plan for your exact stack.

Where this fits in the bigger picture

Outdated dependencies map cleanly onto the security frameworks the analyzer references. In the OWASP Top 10 (2021) this is category A06: Vulnerable and Outdated Components — its own line item precisely because it's so common. The CWE entry is CWE-1104: Use of Unmaintained Third Party Components, and each specific bug rolls up to its own weakness (XSS is CWE-79, prototype pollution is CWE-1321, ReDoS is CWE-1333). In NIST Cybersecurity Framework 2.0 it lives under Identify → Asset Management and Protect → Platform Security; in the CIS Critical Security Controls it's Control 2: Inventory and Control of Software Assets. Knowing the framework label matters when you have to hand the finding to anyone else — an insurer, an auditor, an MSP — because that's the language they file it under.

If you're building and maintaining sites for clients, dependency currency is the kind of recurring, unglamorous maintenance that quietly justifies a retainer. I wrote about turning that exact work into a sustainable practice in The $20 Dollar Agency — the chapter on productized maintenance is built around findings like this one.

The honest limits

Version detection from the wire is fingerprint-based, so a couple of caveats apply:

  • A site that self-hosts libraries with no version in the filename and no banner may not be fingerprintable. That's fine for security-through-obscurity, but it means a clean scan isn't proof you're current — only proof nothing advertised an old version.
  • Manifest-declared ranges (^4.17.0) describe what the build allows, not necessarily what shipped. The analyzer flags the range when its floor permits a known-vulnerable release, and says so.
  • The baseline of "latest" and "security floor" is a dated snapshot, refreshed periodically. Treat the CVE numbers as the durable part and re-check the exact latest version against npm before you pin it.

Related reading

Fact-check notes and sources

  • jQuery XSS: CVE-2020-11022 and CVE-2020-11023, fixed in jQuery 3.5.0. https://github.com/advisories/GHSA-gxr4-xjj5-5px2
  • Bootstrap XSS: CVE-2019-8331 (fixed 3.4.1 / 4.3.1) and CVE-2018-14041/14042. https://github.com/advisories
  • Lodash: CVE-2021-23337 and CVE-2020-8203, fixed in 4.17.21. https://github.com/advisories/GHSA-35jh-r3h4-6jhm
  • Handlebars: CVE-2021-23369, prototype pollution, fixed 4.7.7. https://github.com/advisories
  • AngularJS end-of-life January 2022. https://docs.angularjs.org/misc/version-support-status
  • Moment.js project status (maintenance/legacy mode). https://momentjs.com/docs/#/-project-status/
  • OWASP Top 10 2021, A06 Vulnerable and Outdated Components. https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components/
  • CWE-1104 Use of Unmaintained Third Party Components. https://cwe.mitre.org/data/definitions/1104.html
  • NIST Cybersecurity Framework 2.0. https://www.nist.gov/cyberframework
  • CIS Critical Security Controls v8.1, Control 2. https://www.cisecurity.org/controls

This post is informational, not security-consulting, legal, or compliance advice. CWE and CVE are maintained by The MITRE Corporation; OWASP is a trademark of the OWASP Foundation. All references are nominative fair use. Only scan sites you own or have explicit written authorization to test.

← Back to Blog

Accessibility Options

Text Size
High Contrast
Reduce Motion
Reading Guide
Link Highlighting
Accessibility Statement

J.A. Watte is committed to ensuring digital accessibility for people with disabilities. This site conforms to WCAG 2.1 and 2.2 Level AA guidelines.

Measures Taken

  • Semantic HTML with proper heading hierarchy
  • ARIA labels and roles for interactive components
  • Color contrast ratios meeting WCAG AA (4.5:1)
  • Full keyboard navigation support
  • Skip navigation link
  • Visible focus indicators (3:1 contrast)
  • 44px minimum touch/click targets
  • Dark/light theme with system preference detection
  • Responsive design for all devices
  • Reduced motion support (CSS + toggle)
  • Text size customization (14px–20px)
  • Print stylesheet

Feedback

Contact: jwatte.com/contact

Full Accessibility StatementPrivacy Policy

Last updated: April 2026