Skip to main content
Security7 min read

Rank Your Upgrades by Real-World Exploitability

You know you are behind on upgrades. The hard question is which one to do first. `vg fix` reads your drift and returns three ranked plans — safe, balanced, and full — scored on which vulnerabilities are actually being exploited, so the dangerous upgrade rises to the top instead of getting lost in a list of forty.

Every team carries a backlog of upgrades it means to get to. The list is easy to make and hard to act on, because sorting by how far behind a package is tells you nothing about how much it matters. A dependency five major versions back might be harmless. The one that is a single patch behind might carry a flaw that attackers are exploiting today.

vg fix answers the question the list can't: which upgrade should you do first? It reads your drift — the gap between the versions you run and the latest stable releases — and returns three ranked upgrade plans, scored on real-world exploitability.

Example vg fix output — three ranked plans, prioritised by exploitability.
Example vg fix output — three ranked plans, prioritised by exploitability.

The problem with "just upgrade everything"

Upgrading everything at once is how you turn a quiet afternoon into a three-day firefight. A blanket bump pulls in breaking changes you didn't need, on packages that were never a risk, all to reach a version nobody asked for. So teams do the opposite — they wait — and the risk that mattered sits untouched next to forty that didn't.

The missing piece is prioritisation you can trust. Not "newest first" and not "most versions behind," but most dangerous, given what is actually happening in the wild.

Three plans, ranked by risk

Run the planner at the root of your project:

Terminal
$ vg fix

Vibgrate fix — upgrade plan
12 drifted dependencies analysed
⚠ 2 packages carry a KNOWN-EXPLOITED (KEV) advisory, peak EPSS 74% — prioritise these.

● recommended  Low-risk — patch and minor updates only
    risk 12/100 low  ·  5 upgrades  ·  fixes 1 critical, 2 high  ·  DriftScore 58 → 54
    lodash 4.17.19 → 4.17.21   closes a prototype-pollution advisory

○ Full — everything to latest stable
    risk 58/100 high  ·  12 upgrades  ·  DriftScore 58 → 31

Each plan is a real, ordered set of upgrades with a risk score, the number of advisories it closes, and the DriftScore — our 0–100 measure of how far your stack has drifted — you would land on. You pick the trade-off: the Low-risk plan clears the urgent advisories with patch and minor bumps, while Full takes you all the way to the latest stable at the cost of more churn.

Exploitability, not just severity

Most tools stop at severity. A CVSS score of 9.8 looks alarming, but severity describes the worst case — it doesn't tell you whether anyone has ever exploited the flaw. vg fix layers two public signals on top of the advisory data so the ranking reflects reality, not just theory:

  • CISA KEV — the Known Exploited Vulnerabilities catalog. If a flaw is on this list, it is being exploited in the wild. That is the strongest possible reason to move it to the front.
  • FIRST EPSS — the Exploit Prediction Scoring System, a probability that a vulnerability will be exploited in the near term.

A package that is on KEV with a high EPSS score outranks a higher-CVSS flaw that no one has ever weaponised. That is the difference between a queue sorted by fear and a queue sorted by evidence.

It re-scans so the plan matches your tree

A plan built from a stale scan is worse than no plan. If a manifest or lockfile has changed since your last scan, vg fix notices and re-runs the drift scan first, so the recommendations describe the code you have right now — not the code you had last week.

Terminal
$ vg fix
Scan is out of date (package-lock.json changed since the last scan) —
re-running a drift scan first…

Read-only by default — you decide when to apply

vg fix plans; it does not touch your project unless you tell it to. Every state-changing action goes through an explicit choice, never a quiet auto-apply. To print the plans and stop, pass --no-apply. To preview the exact changes without writing them, use --dry-run. When you are ready, apply a specific tier non-interactively:

Terminal
# Preview only — never edits the project
$ vg fix --no-apply

# Apply the low-risk plan without prompting
$ vg fix --plan safe --yes

The plan tiers are safe, balanced, and aggressive; applying one runs your project's own package manager to make the changes. Drift scoring and the code map are free. The ranked planner is a hosted capability, so vg fix needs a login — run vg login once, or set a VIBGRATE_DSN. It reads only your dependency versions and aggregate usage signals; it never uploads your source.

Wire it into CI

vg fix earns its place in a pipeline with one flag. --fail-on-vulns exits non-zero when the recommended plan would still leave an advisory at or above the severity you name — so a pull request can't merge while a known-exploited flaw goes unaddressed:

Terminal
$ vg fix --no-apply --fail-on-vulns high

Try it

Point it at any project you own:

Terminal
$ vg login
$ vg fix

Prefer to read the flags first? The vg fix command reference lists every option, and Drift is your next CVE explains why staying current is a security control, not just hygiene. To see the free drift scoring that feeds the planner, start at the Vibgrate CLI page.

Vibgrate CLI

See a real scan run

A replay of the actual CLI running against our test repositories — live progress, real findings, a genuine DriftScore. Nothing executes in your browser.

Replay
demo@vibgrate — bash
npx @vibgrate/cli scan
 
╭──────────────────────────────────────────╮
Vibgrate Drift Report
╰──────────────────────────────────────────╯
 
── node-turborepo (node) .
Runtime: >=18.0.0 (6 majors behind)
Frameworks:
Turbo: 1.13.4 → 2.10.4 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
1 current 1 1-behind 3 2+ behind 1 unknown
 
── @repo/admin (node) apps/admin
Frameworks:
TanStack Query: 5.101.2 → 5.101.2 (current)
React: 18.3.1 → 19.2.7 (1 behind)
React DOM: 18.3.1 → 19.2.7 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Vite: 5.4.21 → 8.1.4 (3 behind)
Dependencies:
4 current 8 1-behind 3 2+ behind 4 unknown
 
── @repo/api (node) apps/api
Frameworks:
Express: 4.22.2 → 5.2.1 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Vitest: 1.6.1 → 4.1.10 (3 behind)
Dependencies:
7 current 5 1-behind 3 2+ behind 4 unknown
 
── @repo/web (node) apps/web
Frameworks:
Next.js: 14.2.35 → 16.2.10 (2 behind)
React: 18.3.1 → 19.2.7 (1 behind)
React DOM: 18.3.1 → 19.2.7 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
2 current 6 1-behind 3 2+ behind 5 unknown
 
── @repo/config (node) packages/config
Frameworks:
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
2 current 2 1-behind 5 2+ behind 0 unknown
 
── @repo/types (node) packages/types
Frameworks:
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
0 current 0 1-behind 1 2+ behind 1 unknown
 
── @repo/database (node) packages/database
Frameworks:
Prisma: 5.22.0 → 7.8.0 (2 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
1 current 0 1-behind 3 2+ behind 1 unknown
 
── @repo/ui (node) packages/ui
Frameworks:
React: 18.3.1 → 19.2.7 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
React: 18.3.1 → 19.2.7 (1 behind)
Dependencies:
1 current 4 1-behind 1 2+ behind 1 unknown
 
── @repo/utils (node) packages/utils
Frameworks:
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Vitest: 1.6.1 → 4.1.10 (3 behind)
Dependencies:
0 current 1 1-behind 2 2+ behind 1 unknown
 
Tech Stack
Frontend: React, React DOM
Meta-frameworks: Next.js
Bundlers: tsx, Turbo, Vite
CSS / UI: Autoprefixer, PostCSS, Tailwind CSS
Backend: Express
ORM / Database: Prisma, Prisma Client
Testing: Vitest
Lint & Format: ESLint, ESLint Prettier, ESLint React, Prettier, typescript-eslint
 
Services & Integrations
Auth: JWT 9.0.3
Databases: Prisma 5.22.0
 
TypeScript
v5.3.3 · strict ✔ · MIXED · target: ES2022
 
Build & Deploy
Package Managers: pnpm
Monorepo: npm-workspaces, pnpm-workspaces, turbo
 
Product Purpose Signals
Frameworks: react, nextjs
Evidence: 177
Top Signals:
- [heading] Dashboard (apps/admin/src/pages/Dashboard.tsx)
- [title] Revenue Overview (apps/admin/src/pages/Dashboard.tsx)
- [copy] workspace:* (packages/ui/package.json)
- [copy] ./dist (packages/ui/tsconfig.json)
- [copy] ./src/index.ts (packages/ui/package.json)
- [copy] @repo/config/tsconfig-base.json (packages/ui/tsconfig.json)
- [copy] @repo/ui (packages/ui/package.json)
- [copy] #3b82f6 (apps/admin/src/pages/Dashboard.tsx)
Unknowns:
- No pricing or billing evidence found.
- No integrations/connectors evidence found.
- No route structure evidence found.
 
Security Posture
Lockfile ✖ · .env ✔ · node_modules ✔
 
Platform
Native modules: turbo
 
Code Quality
Files: 36 · Functions: 183 · Avg complexity: 2.62 · Avg length: 21.13 lines
Max nesting: 2 · Circular deps: 0 · Dead code: 0%
God files: apps/admin/src/pages/Products (448 lines)
 
Findings (16 errors, 11 warnings)
Node.js runtime ">=18.0.0" reached end-of-life on 2025-04-30 (latest: 24.0.0).
vibgrate/runtime-eol in .
TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in .
60% of dependencies are 2+ major versions behind in node-turborepo.
vibgrate/dependency-rot in .
@types/node is 6 major versions behind (spec: ^20.11.0, latest: 26.1.1).
vibgrate/dependency-major-lag in .
TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in apps/admin
Vite is 3 major versions behind (current: 5.4.21, latest: 8.1.4).
vibgrate/framework-major-lag in apps/admin
vite is 3 major versions behind (spec: ^5.0.12, latest: 8.1.4).
vibgrate/dependency-major-lag in apps/admin
TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in apps/api
Vitest is 3 major versions behind (current: 1.6.1, latest: 4.1.10).
vibgrate/framework-major-lag in apps/api
@types/node is 6 major versions behind (spec: ^20.11.0, latest: 26.1.1).
vibgrate/dependency-major-lag in apps/api
vitest is 3 major versions behind (spec: ^1.2.1, latest: 4.1.10).
vibgrate/dependency-major-lag in apps/api
Next.js is 2 major versions behind (current: 14.2.35, latest: 16.2.10).
vibgrate/framework-major-lag in apps/web
TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in apps/web
@types/node is 6 major versions behind (spec: ^20.11.0, latest: 26.1.1).
vibgrate/dependency-major-lag in apps/web
TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/config
56% of dependencies are 2+ major versions behind in @repo/config.
vibgrate/dependency-rot in packages/config
eslint-plugin-react-hooks is 3 major versions behind (spec: ^4.6.0, latest: 7.1.1).
vibgrate/dependency-major-lag in packages/config
TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/types
100% of dependencies are 2+ major versions behind in @repo/types.
vibgrate/dependency-rot in packages/types
Prisma is 2 major versions behind (current: 5.22.0, latest: 7.8.0).
vibgrate/framework-major-lag in packages/database
TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/database
75% of dependencies are 2+ major versions behind in @repo/database.
vibgrate/dependency-rot in packages/database
TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/ui
TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/utils
Vitest is 3 major versions behind (current: 1.6.1, latest: 4.1.10).
vibgrate/framework-major-lag in packages/utils
67% of dependencies are 2+ major versions behind in @repo/utils.
vibgrate/dependency-rot in packages/utils
vitest is 3 major versions behind (spec: ^1.2.1, latest: 4.1.10).
vibgrate/dependency-major-lag in packages/utils
 
╭──────────────────────────────────────────╮
Top Priority Actions
╰──────────────────────────────────────────╯
 
1. Upgrade EOL runtime in node-turborepo
End-of-life runtimes no longer receive security patches and block ecosystem upgrades.
./.
>=18.0.0 → 24.0.0 (6 majors behind)
Impact: −10 drift points (runtime & EOL)
 
2. Fix security posture: no lockfile found
Without a lockfile, installs are non-deterministic. Run the install command to generate one and commit it.
./
Missing: package-lock.json, pnpm-lock.yaml, or yarn.lock
 
3. Upgrade Vite 5.4.21 → 8.1.4 in @repo/admin (+2 more)
3 major versions behind. Major framework drift increases breaking change risk and blocks access to security fixes and performance improvements.
./apps/admin
Vite: 5.4.21 → 8.1.4 (3 majors behind)
./apps/api
Vitest: 1.6.1 → 4.1.10 (3 majors behind)
./packages/utils
Vitest: 1.6.1 → 4.1.10 (3 majors behind)
Impact: −5–15 drift points
 
4. Reduce dependency rot in @repo/types (100% severely outdated)
1 of 1 dependencies are 2+ majors behind. Run `npm outdated` and prioritise packages with known CVEs or breaking API changes.
./packages/types
typescript: 5.9.3 → 7.0.2 (2 majors behind)
Impact: −5–10 drift points
 
5. Reduce dependency rot in @repo/database (75% severely outdated)
3 of 4 dependencies are 2+ majors behind. Run `npm outdated` and prioritise packages with known CVEs or breaking API changes.
./packages/database
@prisma/client: 5.22.0 → 7.8.0 (2 majors behind)
prisma: 5.22.0 → 7.8.0 (2 majors behind)
typescript: 5.9.3 → 7.0.2 (2 majors behind)
Impact: −5–10 drift points
 
╭──────────────────────────────────────────╮
Architecture Layers
╰──────────────────────────────────────────╯
 
Archetype: monorepo (80% confidence)
Files classified: 29 (6 unclassified)
 
presentation 9 files drift ████████████████████ 100 risk high
routing 4 files drift ████████████████████ 100 risk high
middleware 2 files drift ███████▍░░░░░░░░░░░░ 37 risk moderate
domain 4 files drift ████████████████████ 100 risk high
data-access 2 files drift ████████████████████ 100 risk high
infrastructure 0 files drift ░░░░░░░░░░░░░░░░░░░░ 0 risk none
config 3 files drift ░░░░░░░░░░░░░░░░░░░░ 0 risk none
shared 5 files drift ████████████████████ 100 risk high
testing 0 files drift ████████████████████ 100 risk high
 
╭──────────────────────────────────────────╮
DriftScore Summary
╰──────────────────────────────────────────╯
 
DriftScore: 76/100
Risk Level: HIGH
Projects: 9
Classified: 8 nano · 1 micro · 0 small · 0 standard
Billable: 0.42 · 9 detected → 0.42 billable projects (micro-project pricing)
0.1 micro · 0.32 nano
These fractions add up across repositories, then round down to whole billable projects.
 
Score Breakdown
Runtime: ████████████████████ 100
Frameworks: █████████▏░░░░░░░░░░ 46
Dependencies: ██████████████████▍ 92
EOL Risk: ████████████████████ 100
 
Scanned at 2026-07-11T21:07:49.557Z · 27.1s · 285 files scanned · 56 workspace files · 27 dirs
Press Run to start.