DEV Community

Cover image for Why Cursor Installs npm Packages With Known CVEs
Charles Kern
Charles Kern

Posted on • Originally published at safeweave.dev

Why Cursor Installs npm Packages With Known CVEs

TL;DR

  • Cursor and other AI editors recommend package versions frozen at their training cutoff, so the "latest" version they suggest can already carry a known CVE the day you install it.
  • Axios 1.6.0 through 1.7.3 ships CVE-2024-39338, a real SSRF, but a model trained before August 2024 still hands it to you as a safe, modern pick.
  • The fix is not a better prompt. Run npm audit at generation time and let the advisory database, not the model's memory, decide what version you install.

I asked Cursor to add an HTTP client to a small Node service last month. It wrote the fetch logic, added axios to package.json, pinned it to ^1.6.0, and told me that was the current stable release. It looked right. It installed clean. Tests passed.

Then npm audit lit up with a high-severity SSRF.

The version Cursor picked was not made up. It was a real axios release that really was recent at some point. The problem is that "recent" for the model means recent as of its training data, and a lot has been disclosed since then.

The Vulnerable Code

The vulnerability is not in the code the AI writes. It is in the version number it pins. Here is what Cursor added to my package.json:

{
  "dependencies": {
    "axios": "^1.6.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

That caret range resolves to the newest 1.x release my lockfile allowed, which landed on 1.7.3. Axios 1.7.3 is affected by CVE-2024-39338 (CVSS 7.5, HIGH): path-relative request URLs get processed as protocol-relative URLs, so an attacker can coerce the server into making requests to internal services. That is a textbook SSRF, sitting in a dependency I never chose by hand. The same range also passes through CVE-2023-45857, where the XSRF-TOKEN cookie leaks to unintended hosts on every request in versions below 1.6.0.

None of this shows up when you read the generated code. The axios.get(userUrl) call looks fine. The vulnerability lives one file over, in the version pin.

Why This Keeps Happening

AI editors recommend versions from memory, and their memory stops at the training cutoff. A model trained before August 2024 has never seen the axios 1.7.4 release that fixed CVE-2024-39338, so it cannot warn you about a CVE that was disclosed after it stopped learning.

Think about what the model actually knows. During training it read millions of package.json files, changelogs, and tutorials, all written before its cutoff. From that it learns that axios 1.6.x and 1.7.x are modern, widely used, and stable, because at the time those files were written, they were. It has no channel to the CVE feed. It cannot know that 1.7.4 shipped on August 13, 2024 specifically to patch an SSRF, because that happened after the snapshot it was trained on.

So the model does the reasonable thing with stale information. It gives you the newest version it remembers and calls it current. The version is not hallucinated. It is just frozen in time, and time keeps moving.

This is why "just use a newer model" does not solve it either. Every model has a cutoff. The gap between that cutoff and the day you run the prompt is always growing, and CVEs get disclosed in that gap every week.

The Fix

Never trust a model's version pin. Verify it against the advisory database at generation time with npm audit, and upgrade to the patched release the audit points you to.

# Right after the AI adds a dependency, before you commit:
npm audit

# For the axios case, the fix is a version bump the model did not know existed:
npm install axios@^1.7.4   # 1.7.4 patched CVE-2024-39338

# Let audit apply compatible fixes across the whole tree:
npm audit fix
Enter fullscreen mode Exit fullscreen mode

Make it automatic so you do not have to remember. A pre-commit hook or a CI step turns this from a habit into a guarantee:

# .github/workflows/audit.yml
- name: Dependency audit
  run: npm audit --audit-level=high
Enter fullscreen mode Exit fullscreen mode

Python is the same story with different tools. pip install requests from an AI suggestion can pin a version with a known CVE just as easily, so run pip-audit in the same spot:

pip-audit            # flags known CVEs in installed packages
pip-audit --fix      # bumps to patched versions where it can
Enter fullscreen mode Exit fullscreen mode

The rule is simple. The model chooses the version from memory. The audit tool chooses it from the current advisory feed. Only one of those two is looking at CVEs disclosed this month.

FAQ

Q: Does using the latest AI model fix this?
A: No. Every model has a training cutoff, and CVEs are disclosed continuously after it. A newer model shortens the stale window but never closes it, so you still have to audit dependencies at install time.

Q: How do I catch a vulnerable version an AI editor pinned?
A: Run npm audit (or pip-audit for Python) immediately after the AI adds a dependency, and add npm audit --audit-level=high to CI so a vulnerable pin fails the build instead of shipping.

Q: Is the AI-generated code itself the problem here?
A: Usually not. The axios.get() call is fine. The risk is the version number in package.json, which the model selected from training data that predates the CVE.

I've been running SafeWeave for this. It hooks into Cursor and Claude Code as an MCP server and audits every dependency the AI pins against the live advisory database before I move on, so a stale version with a known CVE gets flagged the moment it lands. Even a basic CI step with npm audit --audit-level=high will catch most of what's in this post. The important thing is checking versions against a current feed, not the model's memory, whatever tool you use.

Read the full original on the SafeWeave blog: https://safeweave.dev/blog/why-cursor-installs-npm-packages-with-known-cves

Top comments (0)