I built an AI agent that tells you which outdated dependency will actually hurt you

June 25, 2026

Every project has a package.json graveyard. Four outdated packages. Eight CVE notices. A tired developer who upgrades lodash because it's at the top of the list — not because it matters.

The scanner gave you a list. It didn't give you a decision.

That's the problem I spent this hackathon solving.

The insight

There's a difference between a dependency being outdated and a dependency being dangerous.

axios pinned at 0.21.3 with a full major lag, carrying SSRF and credential-leak CVEs, sitting on your network/HTTP path — that's dangerous. debug running one minor behind with no CVEs, imported only in a development util — that's noise.

Both show up in the same flat scanner output. Most teams fix debug first because it's the smallest diff.

The question isn't "which packages are outdated?" It's "which outdated packages are on paths that matter?"

Answering that requires knowing the shape of your codebase — not just its manifest.

What GitLab's Orbit graph changes

GitLab's Orbit knowledge graph indexes your repository as a semantic graph: files, functions, import relationships, call chains, service boundaries. It's queryable via query_graph, and that changes what's possible.

Instead of asking "what imports lodash?", you can ask:

"What services import this package, and are any of those services on the authentication path?"

That traversal — package → importer → service → criticality — is what turns a flat dependency list into a ranked action plan.

The agent

I built a Duo Agent Flow called Dependency Aging Advisor. It lives in the GitLab AI Catalog and runs on any Orbit-indexed project.

The trigger is one comment on any issue:

@ai-dependency-aging-advisor run the dependency aging audit

That's it. The agent then:

  1. Calls get_graph_schema to understand the project's topology
  2. Calls query_graph four times — one traversal per outdated dependency — to find every file and service that imports it
  3. Calls list_vulnerabilities to pull live CVE data
  4. Computes a blast radius score combining: import depth, service criticality, CVE severity, version lag
  5. Files a structured advisory issue with three buckets: Act this month, Track, Ignore

No configuration. No YAML to write. No CI job to add. Just the mention.

The advisory issue it filed

Here's what it produced on the test repository — issue #2, filed automatically by the AI service account:

Act this month

DependencyRiskBlast radiusWhy
axios7.257 — CORE (network/HTTP path)Pinned at 0.21.3. Carries CVE-2021-3749 (SSRF) and CVE-2023-45857 (credential header leak). Network-facing import path amplifies exploitability.
bcrypt5.010 — CRITICAL (auth path)No CVE today, but its sole importer is verifyPassword() on the login path. Any future CVE here immediately becomes act-this-week severity.

Track

DependencyRiskBlast radiusWhy
lodash4.62 — PERIPHERALCarries CVE-2021-23337 (command injection). Import graph found no active usage in indexed source files.

Ignore

debug — no CVE, one minor version behind, dev-only usage.

Same four packages. Completely different priorities. That's the point.

The engine

The core is orbit_client.py — 400 lines of Python stdlib. No external dependencies. Dual auth (PRIVATE-TOKEN + Bearer), project-scoped traversal via traversal_path, and a graceful ripgrep fallback for when Orbit isn't available.

The test suite runs six scenarios against a fixture npm app with intentionally outdated packages. All six pass.

The CI pipeline schedules it weekly so the advisory stays current without anyone having to remember to run it.

What I learned building this

The graph is the unlock. The difference between "which packages are outdated" and "which packages will hurt you" is entirely about topology. query_graph makes that traversal cheap. Without it, you'd need static analysis tooling, custom AST parsing, and a lot of project-specific configuration. With it, you write a prompt.

Blast radius is a better unit than CVE score. CVSS scores are decontextualised. A CVSS 9.8 on a package that only runs in a weekend batch job is less urgent than a CVSS 5.0 on something sitting on your login path. The agent scores both dimensions and lets them interact.

The @mention interface is underrated. I almost added a CLI. I almost added a dashboard. The right answer was: one comment, in the place developers already are, producing output in the same place. No friction, no context switch, no new tool to learn.

Agentic doesn't mean autonomous. The agent doesn't patch anything. It doesn't open PRs. It files an issue with the evidence and the reasoning, and a human makes the call. That's the right boundary — automate the research, not the consequence.

Links

The flow is public and enabled on any Orbit-indexed project with a single click. If you run it on your repo, I'd be curious what it finds.