Back to articles
Vibe CodingDependenciesSupply ChainAI

Dependency Safety for Vibe-Coded Apps

AI agents casually npm install whatever makes the error go away — typosquats, dead packages, CVEs, bundle bloat. How to vet dependencies before you accept them.

Yash Thakur
4 min read
Dependency Safety for Vibe-Coded Apps

The short answer: The fastest way a vibe-coded app gets compromised isn't your code — it's a dependency the agent casually npm installed to make an error go away. Agents pull packages with lookalike typosquat names, abandoned libraries, known CVEs, and a 2MB dependency to do a one-line job. The fix is boring and total: vet every package before you accept it, pin exact versions, commit the lockfile, and let a scanner fail the build. Treat every dependency as code you are personally shipping, because you are.

Your own code gets reviewed. The 40 transitive packages an agent dragged in to satisfy one import do not — and that's where the risk lives. A dependency runs with the same privileges as the rest of your app: it can read your env vars, make network calls, and touch the filesystem. "The agent added it and the build passed" is not a security review. Here's the one you actually need.

1. Vet the package before you accept it

When an agent proposes a dependency, it's optimizing for "makes the code work," not "is this thing trustworthy." Three checks, every time, before the install lands:

  • Is it real? Typosquatting is the oldest supply-chain trick — a malicious package named one character off a popular one (lodahs for lodash, crossenv for cross-env, discordjs for discord.js). An agent that half-remembers a name will install the wrong one without blinking. Confirm the exact name against the official docs or the real repo, not the agent's memory.
  • Is it maintained? Recent releases, issues that get answered, a commit history that didn't stop two years ago. An abandoned package is an unpatched CVE waiting to happen and a dependency you'll be forced to rip out later.
  • Is it popular? Download counts aren't proof of safety, but a package with millions of weekly downloads has thousands of eyes on it. A package with 40 downloads and no stars that the agent reached for is worth a hard look.

2. Pin exact versions — never open ranges

This is the single highest-leverage habit. Agents (and npm install defaults) write caret ranges like ^1.2.0, which means "any 1.x newer than this." That's a standing invitation for a future install to silently pull a version you never reviewed — including the one an attacker published after compromising a maintainer's account.

Exact versions make your builds reproducible and your supply chain auditable: an upgrade becomes a deliberate, reviewable change in a diff, not something that happens behind your back at 2am on a CI runner.

3. Commit the lockfile, and watch for the typosquat

The lockfile (package-lock.json, pnpm-lock.yaml, yarn.lock) records the exact resolved version and an integrity hash for every package and every transitive dependency. Commit it. Then npm ci on CI installs that exact tree and fails if anything doesn't match the hash — which is your tripwire against a tampered package.

And when you read a lockfile or a proposed install, read the name like an attacker wrote it:

4. Scan in CI, prefer the platform, and watch the weight

Three more habits that close the loop:

  • Run npm audit (or Snyk / Dependabot / osv-scanner) in CI, and make a high-severity finding fail the build. A vulnerability flagged in a pull request is a fix; the same one discovered in production is an incident.
  • Prefer the platform over a dependency. Modern JS has fetch, structuredClone, crypto.randomUUID(), Intl, Array.prototype.flat. Agents reach for a package out of habit — node-fetch, a uuid lib, a left-pad — when the runtime already ships the capability. Every dependency you don't add is a supply-chain risk you never took.
  • Audit the bundle cost. Pulling a 300KB date library to format one timestamp, or all of lodash for a single get, is bloat the agent won't think about. Check the weight (bundlephobia, source-map-explorer) and reach for a lighter alternative or a few lines of your own.

The one-pass checklist

Before you accept a dependency a vibe-coding agent added, run this:

  • [ ] Package name verified against the official source — not a typosquat
  • [ ] Actively maintained (recent releases, answered issues)
  • [ ] Popular enough to have real scrutiny (download counts)
  • [ ] Pinned to an exact version, no ^ or ~
  • [ ] Lockfile committed; CI uses npm ci (not npm install)
  • [ ] npm audit / a scanner runs in CI and fails on high-severity CVEs
  • [ ] Could the platform or stdlib do this instead?
  • [ ] Bundle cost checked — not a heavy lib for a trivial job

Use agents and skills deliberately

Dependency safety is a place where pointing a specialist agent at the generalist's output pays off directly. The agent that wrote the feature was optimizing for "works"; a reviewer with a narrower brief catches the supply-chain mistakes it never considered.

  • A security-and-hardening skill to audit new and existing dependencies for known CVEs, unmaintained packages, and suspicious names before you accept them.
  • A performance-optimization skill to flag bundle bloat — a heavy library pulled in for a trivial task, or a dependency that duplicates something the platform already provides.
  • A dependency/vulnerability scan wired into CI so a flagged package fails the build instead of reaching production.

Dependencies are the part of a vibe-coded app you didn't write but are fully responsible for. The agent treats npm install as free; you can't. Vet the package, pin the version, commit the lockfile, scan in CI — and the casual install stops being the weakest link in your supply chain.

This is one of the vibe-coding deep-dives — start from the vibe-coding precautions overview. It pairs closely with security and networking precautions, where the same scanner-in-CI habit lives, and the frontend precautions, where bundle weight hits hardest.

Frequently asked questions

How do I check if an npm package is safe to install?

Before accepting it, confirm the package is real and not a typosquat of a popular name, check it's actively maintained (recent releases, open issues getting answered), look at weekly download counts for popularity, and run npm audit against it. A package with no recent commits, few downloads, or a name one character off a famous library is a red flag.

Should I pin exact dependency versions or use ranges like ^1.2.0?

Pin exact versions for anything you care about reproducing or securing. A caret or tilde range lets a future install silently pull a newer release — which is exactly how a compromised version enters your build. Exact versions plus a committed lockfile mean every install, everywhere, resolves to the same bytes you reviewed.

Why does a lockfile matter for AI-generated projects?

The lockfile records the exact resolved version and integrity hash of every dependency and transitive dependency. Commit it, and your CI, your teammates, and your production build all install the identical tree you tested. Without it, 'it worked on my machine' becomes a supply-chain gamble every time someone runs install.

Written by Yash Thakur

Senior React Developer · 8+ years building for the web

More articles

Keep reading