Skip to content
Back to field notes
DependenciesJune 6, 20266 min read

Outdated dependencies as a launch blocker: what to check and what to defer

Not every outdated package should hold your launch. This note gives a repeatable triage so you can tell a known-vulnerable dependency (blocker) from a merely stale one (defer).

DependenciesnpmLaunch triage

Outdated is not the same as vulnerable

The launch risk here is a decision risk, not a single exploit. When you run npm outdated the day before launch and see thirty packages behind their latest version, the wrong move is to treat all thirty as equally urgent. Some of them ship a known security flaw that an attacker can look up and target the moment your URL spreads. Most of them are simply behind and carry no published vulnerability at all. Conflating the two either delays a launch for no security reason, or worse, hides the one package that actually matters under twenty-nine that do not.

Separate what is known from what is merely old:

The goal of this note is a triage you can run in a few minutes: which findings hold the launch, which get a ticket for next week.

  • A package with a published advisory has a documented flaw and often a fixed version. This is observable: npm audit reports it, with a severity and an affected range. It is a candidate launch blocker.
  • A package that is just behind its latest release has no advisory tied to it. Being outdated is a maintenance fact, not a vulnerability. It is hardening you can schedule.
  • Outdated does not imply exploitable, and current does not imply safe. A freshly published version can introduce a new flaw, and an old version with no advisory may be perfectly fine to ship.

Why AI-built apps arrive with a stale, unreviewed tree

AI scaffolds optimize for an app that runs, not a dependency tree someone has reviewed. A generator pins whatever versions it knows, wires them up, and produces a working build. That build looks finished because it functions, which is exactly why the dependency state goes unexamined.

None of this is unique to AI tools, but the combination of an old default tree plus a skipped review plus a same-day deploy is the pattern these builds hit.

  • The model's training has a cutoff, so the versions it reaches for can already be months old on the day it writes them. The app still runs, so nothing flags the gap.
  • The review loop where a human runs npm audit and reads the advisories is the step that does not happen automatically. The generated code does not remind you to do it.
  • Fast deploy means the public URL exists before anyone has looked at what is in node_modules. Dependency freshness is invisible from inside a working app.
  • Transitive dependencies make it worse: the flaw is rarely in a package you chose, it is in something three levels down that a direct dependency pulled in.

A repeatable triage with npm outdated and npm audit

Run two commands on your own project and read them as a pair. They answer different questions, and only one of them is about security.

npm outdated lists every package behind its latest published version. It shows the current, wanted, and latest columns. This tells you about freshness, not risk. Read it to understand how far behind you are and where a major version jump is waiting, but do not treat a row here as a blocker on its own.

npm audit reads your installed tree against the advisory database and reports packages with known vulnerabilities, each with a severity and the range that fixes it. This is the security signal. For a production launch decision, run it against the dependencies you actually ship, for example npm audit --omit=dev or npm audit --production, so a vulnerability that only exists in a build-time or test tool does not get counted as a runtime launch blocker. Note what omitting dev hides, though: a flaw in a dev dependency can still matter if that tool runs in your build pipeline.

  • Safe-looking result: npm audit reports zero vulnerabilities for your production tree, and npm outdated shows packages behind but with no advisory against them. That is a clean launch signal on the dependency axis and a hardening backlog, not a blocker.
  • Suspicious result: npm audit reports a high or critical advisory in a package that runs in production, especially anything network-facing, a parser, a serializer, or your framework. That is a candidate blocker. Read the advisory, do not just read the severity.
  • Severity is a starting point, not a verdict: a high-severity flaw in a code path your app never calls may be lower real risk than a moderate one in your request handler. The advisory text tells you the affected functionality; match it against what your app does.

Fix-now versus defer, and what neither covers

Once you have the audit output, sort each finding into fix-now or defer with criteria you can defend.

Fix now, before the URL spreads:

Defer to a scheduled update:

What this triage does not cover, state it plainly:

  • A known advisory (high or critical) in a package that runs in production and sits on a reachable path, with a fixed version available. Patch to the fixed version and redeploy.
  • Anything in your request-handling, auth, parsing, or serialization path, even at moderate severity, when a fix exists.
  • Outdated packages with no advisory against them. Being behind is not a launch risk; batch these into a maintenance window.
  • A major version bump that exists only to stay current and carries breaking changes. Major upgrades change APIs and can introduce new bugs, so doing one under launch pressure trades a hypothetical risk for a real regression. Pin the safe version now, plan the major upgrade deliberately.
  • An advisory in a dev-only tool that never runs in production or your build pipeline.
  • It does not find vulnerabilities with no published advisory yet, including zero-days and flaws in packages no one has reported.
  • It does not catch a malicious package that was deliberately published, a typosquat, or a compromised maintainer release. The advisory database is reactive.
  • It does not confirm your installed tree matches what you tested. Without a committed lockfile, production can resolve different versions than your machine did, which is a separate concern from freshness.

npm audit tells you what the ecosystem currently knows is broken. A zero result means no published advisory matched your tree today, not that your dependencies are safe. Re-run it close to launch and again after deploy, because the database changes daily.

Where VibeCodeGuard fits, and what it does not prove

This triage is a local, repository-level step. You run npm outdated and npm audit against your own code and lockfile, because that is where the dependency tree lives. VibeCodeGuard's Launch Check does not run on your repository; it scans the deployed public URL. It surfaces the public-surface signals an outside visitor can reach, such as exposed source maps, secret-shaped strings in the client bundle, missing security headers, open or wildcard CORS, and reachable build or deploy artifacts.

So the relationship is complementary. The dependency triage in this note is the framework that informs your launch decision from inside the code. The Launch Check is a separate signal about what your live app exposes from outside. A clean scan does not read your package.json, your audit output, or your lockfile, and it cannot tell you whether a dependency three levels down has a known advisory. For the dependency-freshness launch check itself, run npm audit yourself, as covered in the related note on npm audit before launch and the deeper look at vulnerable packages in Vite and Next.js apps.

A clean Launch Check on the public surface is not evidence that your dependency tree is patched, and a clean npm audit is not evidence your public surface is safe. They answer different questions. Treat a high or critical production advisory as a launch blocker, batch the merely outdated packages into a maintenance window, and run a focused Launch Check against the public URL before you share it.

> launch check

Scan the public surface before launch.

Get severity, evidence, and practical fix guidance for the checks VibeCodeGuard can run from the outside.