The Five npm Packages AI Coding Assistants Keep Recommending — and Why Each One Belongs Nowhere Near Production
Every vibe-coded codebase we audit at Wolf-Tech looks different on the surface. Different domains, different founders, different product ideas. But underneath, the dependency list tells a familiar story. The same five or six npm packages appear again and again — installed not because the developer chose them, but because Cursor, Copilot, or ChatGPT suggested them and the developer accepted without question.
That is not a knock on AI coding assistants. They are genuinely useful, and the packages they recommend were often the right choice at some point in time. The problem is that AI models are trained on historical code. They cannot see that a maintainer deprecated their package in 2020, that a supply-chain incident poisoned a release in 2022, or that the JavaScript ecosystem moved on and left a once-popular library behind.
By the time a vibe-coded SaaS reaches us — usually after a failed security audit, a performance wall, or a due-diligence request from an investor — these packages have become quiet liabilities. Here are the five we find most often, why each one is a problem in 2026, and the modern alternative we install in its place.
1. request — the HTTP client that has been dead for five years
The request package has been deprecated since February 2020. Its maintainer published a formal deprecation notice, linked to alternatives, and stopped accepting security patches. The npm registry still shows it. AI tools still recommend it. It still receives around 15 million weekly downloads because a large slice of the internet has not updated its code.
In a vibe-coded codebase, you will typically see it appear as soon as the app needs to call an external API: Stripe webhooks, third-party data feeds, payment processors, SMS gateways. Cursor or ChatGPT generates a handler, reaches for request, and the developer installs it without checking the npm page.
The concrete risk: when a vulnerability is discovered in request's dependency chain — and they are being discovered, because the package still has transitive dependencies that do get updated — there is no maintainer to patch it. Your npm audit will flag it, your CI will fail, and your only fix is migrating away.
The replacement we install: Node.js 18+ ships with native fetch. For complex use cases that need interceptors, retry logic, or a streaming API, we reach for got or undici. Zero extra dependencies for basic API calls; purpose-built libraries for the cases that actually need them.
2. moment — the date library that ships 200 KB you do not need
The moment.js maintainers wrote a public statement in 2020 saying: "We now generally consider Moment to be a legacy project in maintenance mode." They recommended migrating to modern alternatives. The package still works. But it brings 67 KB of gzipped JavaScript — and it is not tree-shakeable, so you pay for the full bundle even if you only call moment().format().
In 2026, every major bundler optimizes for tree-shaking. A modern SaaS should load in under three seconds on a 4G connection. Moment makes that harder for no gain. Worse, moment objects are mutable. moment().add(1, 'day') modifies the original object in place. This creates bugs that are genuinely difficult to reproduce because they depend on call order across components.
AI assistants default to moment because it dominated the JavaScript ecosystem for nearly a decade. Their training data is saturated with it. We find it in dashboards, billing pages, admin panels — anywhere dates appear.
The replacement we install: dayjs for straightforward formatting needs (2 KB gzipped, nearly identical API to moment, immutable by default). date-fns for complex date arithmetic (fully tree-shakeable, pure functions, no prototype pollution). The migration from moment to dayjs typically takes an afternoon for a mid-size codebase.
3. colors — a supply-chain incident waiting to repeat itself
The colors package had a dramatic incident in January 2022. Its maintainer intentionally introduced a breaking change to version 1.4.44-liberty that put the package into an infinite loop, corrupting the output of any application that depended on it. Thousands of projects — including the AWS CDK — broke overnight.
The maintainer's motivations were their own grievance with open-source economics. The damage to downstream projects was immediate and real. The episode became a case study in how a single npm maintainer with publish rights can cripple thousands of production applications.
The package recovered (an earlier version was pinned), but it exposed the fundamental fragility of depending on a single-maintainer package with no governance process. AI assistants still recommend colors for adding color to terminal output, because the incident happened after their training cutoffs.
The replacement we install: chalk (well-governed, TypeScript-first, ESM-compatible) or picocolors for minimal use cases. Both have multiple maintainers, clear release processes, and active security monitoring. The API migration from colors to chalk is a find-and-replace operation.
4. uuid v1 — timestamps that leak your server's MAC address
The uuid package itself is fine and actively maintained. The problem is which version AI assistants generate. When you ask Cursor or ChatGPT to add a UUID generator to a Node.js service, they frequently produce uuidv1() — a time-based UUID that encodes both the current timestamp and the network interface's MAC address into the generated ID.
In a SaaS application, UUID v1s that appear in API responses, URLs, or log files expose two things you do not want to expose: the exact time your server generated the record, and a fingerprint of the physical or virtual network interface your server runs on. That second one is a meaningful privacy leak in containerized environments where the MAC address can be correlated with cloud provider assignments.
Beyond the privacy concern, UUID v1 is sequential — IDs generated close together are numerically close. In databases that use B-tree indexes (which is most of them), sequential inserts are fine. But if IDs ever appear in user-facing URLs or external API responses, sequential IDs make enumeration trivial.
The replacement we use: uuidv4() for random, opaque identifiers. If you need sortable IDs with embedded timestamps for log correlation, use ulid instead — it is sortable, URL-safe, and does not leak hardware information.
5. Full lodash imports — 24 KB for a function you could write in one line
lodash is not a bad library. It is well-tested, well-maintained, and genuinely useful. The problem is how AI assistants use it. A common AI-generated pattern looks like this:
import _ from 'lodash';
const grouped = _.groupBy(items, 'category');
That import pulls all of lodash — 24 KB gzipped — into your bundle for a single function. In a server-side Node.js context the bundle size matters less. In a React or Next.js frontend, it adds measurable load time and is entirely unnecessary.
The JavaScript standard library has caught up. Array.prototype.groupBy is in the pipeline. In the meantime, groupBy, debounce, throttle, and most of the lodash functions developers actually use can be implemented in five to ten lines of vanilla JavaScript that are more readable, have no dependencies, and are easier to test.
When we audit vibe-coded frontends, we often find five or six lodash functions used across an entire application — each one added by a different AI prompt, each one pulling the full library. Tree-shaking sometimes catches this (import groupBy from 'lodash/groupBy' gives you the single function), but AI tools rarely generate the path-based import form.
What we install instead: Either named imports (import groupBy from 'lodash/groupBy') or, more often, inline implementations. We also reach for lodash-es when tree-shaking is configured correctly. If an application uses more than ten lodash functions heavily, the full library earns its place — but that threshold is rarely met in the SaaS applications we audit.
The pattern behind the pattern
Each of these packages has the same underlying story: they were excellent when the training data was collected, and the world moved on without the AI knowing. Supply-chain incidents happened. Maintainers wrote deprecation notices. The JavaScript ecosystem built better alternatives.
A vibe-coded application is built fast, which is the point. But the AI's suggestion is always a starting point, not a final decision. The mistake we see consistently is treating AI output as reviewed output — accepting a dependency without checking its npm page, its last publish date, its download trend, and its open issues.
The Renovate configuration snippet we add during every rescue:
{
"packageRules": [
{
"matchPackageNames": ["request", "moment", "colors", "node-uuid"],
"matchCurrentVersion": ">=0.0.1",
"enabled": false,
"description": "Flagged as deprecated or supply-chain risk — migrate to modern alternative"
}
]
}
This tells Renovate to flag these packages on every PR, preventing them from silently returning after a cleanup sprint.
What to do if these packages are already in your codebase
First, run npm audit and npx depcheck to understand the full picture. Then prioritize by risk surface: packages that handle authentication, external HTTP calls, or user-supplied data need to move first. Date formatting libraries and utility packages can follow in the next sprint.
If you inherited a vibe-coded codebase and want a full dependency review — not just the five packages above, but a complete picture of what is deprecated, what has open vulnerabilities, and what should be replaced — our code quality consulting service covers this as part of a broader codebase audit.
We have done this for SaaS teams preparing for Series A due diligence, for founders who just hired their first senior developer and need the codebase in defensible shape, and for companies whose AI-generated MVP needs to become a reliable product. The dependency audit is rarely the biggest problem we find — but it is always a problem we find.
If any of this sounds like your situation, reach out at hello@wolf-tech.io or visit wolf-tech.io to start a conversation. A dependency audit takes one day. The peace of mind lasts considerably longer.

