DependencyIQ

Because severity isn't priority. Context is.

DependencyIQ is a GitLab-native software supply-chain security agent that turns a wall of dependency-vulnerability alerts into one safe, evidenced remediation decision — using GitLab Orbit's repository knowledge graph to know what's actually reachable, and the GitLab Duo Agent Platform to fix it without breaking your code.

Security teams don't suffer from a lack of vulnerability scanners. They suffer from a lack of context — and from how hard it is to safely remove a vulnerability once it's found.


⚡ TL;DR

  • Scanners tell you a dependency is vulnerable. DependencyIQ tells you whether it's reachable, what it would break, and then fixes it — opening a verified merge request, never merging it.
  • It runs as an autonomous, multi-agent Flow on the GitLab Duo Agent Platform: Discover → Plan → Remediate → Verify → Track → Report.
  • The intelligence comes from GitLab Orbit — a real import graph of your code — so a CVSS score becomes a contextual risk score.
  • It works across npm, PyPI, Go, and Maven, including the hard transitive cases where there's no version line to change.
  • Core principle: never fabricate. When Orbit can't answer, it says so — it never invents confidence.

🧩 Inspiration

In 2021, Log4Shell became one of the most severe software vulnerabilities ever discovered. Roughly 70,000 projects depended on Log4j directly — but nearly 174,000 depended on it transitively. The hard part was never finding Log4j. It was answering: where is it actually used? Is it reachable? Which apps are exposed? Which fix is safe to ship? A year later, most organizations were still remediating it — not because they couldn't detect it, but because safely removing a deeply nested dependency is brutal.

Then history repeated itself — while we were building this.

  • March 31, 2026 — axios. Microsoft disclosed that two malicious axios versions had been published with hidden dependencies that installed remote-access trojans during npm install. axios serves 70M+ weekly downloads. Most affected projects never chose the bad version — dependency resolution handed it to them.
  • LiteLLM. Researchers found the compromise by accident, while investigating an unrelated MCP plugin that had pulled LiteLLM in as a transitive dependency. A single compromised publishing pipeline spread it across PyPI, npm, Docker Hub, GitHub Actions, and OpenVSX.

The common theme: the most dangerous code in a project is often code nobody knows is there.

And then I hit it myself. A scanner flagged a vulnerable axios nested several levels deep — pulled in by something else, not by me. The scanner could say "this is vulnerable." It couldn't say: Is it used? Reachable? In production? Behind a public API? Should I upgrade, override, or remove it? I spent hours tracing dependency trees and reading changelogs — for what turned out to be low-impact.

That was the realization:

The industry has optimized vulnerability detection. It has never optimized vulnerability decision-making — or safe remediation.

That gap became DependencyIQ.


🚀 What it does

Traditional scanners answer "what is vulnerable?" DependencyIQ answers "what actually matters, and how do I fix it safely?"

For every vulnerable dependency, it evaluates reachability, exposure, usage, blast radius, the dependency relationship, and the safe remediation path — then turns a raw CVE into an action. The result is a reversal that severity alone can never produce:

lodash   ·  CVSS 9.8              axios   ·  CVSS 6.5
  imported by 0 files               imported by 17 files
  reachable from 0 APIs             reachable from 3 public APIs
  → Dead code. Remove it.           → Urgent. Remediate now.

The "critical" finding becomes a cleanup task; the "moderate" one becomes the top priority. That's only possible because something understands the repository graph.

The features

🤖 An autonomous remediation Flow. Mention the agent on an issue and it runs the whole job on its own — a six-stage pipeline that scans, scores with Orbit context, plans the fix, applies it, verifies the tests still pass, tracks it in GitLab, and reports back. It opens the merge request with the evidence attached — and never merges it. The human stays in control.

🛰️ Orbit-powered blast radius. For each finding it queries GitLab Orbit's import graph: which files actually import the package, whether that code is public-API-facing or internal/test-only, and how far the impact spreads. That's what separates "vulnerable" from "vulnerable and reachable."

🧮 Transparent, context-aware risk scoring. A single 0–100 score that fuses severity with real exposure (formula below) — no black box, every contribution auditable.

🛠️ Safe remediation — even transitive. The painful case is when the vulnerable package is transitive (no line in your code to change). DependencyIQ applies the right mechanism per ecosystem and proves the fix didn't break anything by running your test suite before opening the MR.

🌐 Four ecosystems. Discovery and scoring across everything OSV reads; automated fixes for npm (overrides), Maven (<dependencyManagement>), PyPI (pinned constraints), and Go (require / minimal version selection). It even maps install names to import names (PyYAML → yaml, scikit-learn → sklearn) so a Python or Java package never looks falsely unused.

🧑‍✈️ Four specialized agents, one engine:

Agent Role
DependencyIQ Triage and safely remediate vulnerabilities; live Orbit blast-radius in chat; approval-gated fixes.
Guardian Reviews incoming dependency MRs (Dependabot/Renovate/human) and posts an approve / review / block verdict before they merge.
Emergency Response Org-wide incident triage: given a compromised package, finds every project in the group that imports it — directly or transitively — in minutes, not months.
Freshness Proactive tech-debt governance: flags dependencies drifting past a policy you set in AGENTS.md, before they become security debt.

📊 A live dashboard. Published to GitLab Pages — a decision trail per finding, direct-vs-transitive badges, and an executive roll-up of engineer-hours and breaking-change risk.

🛡️ Honest by design. If Orbit can't answer, exposure contributes 0 and the report says "unavailable" — it never invents importers to look more confident. For a security tool, that's non-negotiable.


🛠️ How we built it

DependencyIQ is one tested engine exposed through many surfaces — CLI, chat agents, the ambient Flow, an Agent Skill, and the dashboard — so the logic lives once and behaves identically everywhere. It's published to npm as dependencyiq, so any GitLab project can run it in its own CI without vendoring source.

  • GitLab Orbit — the repository knowledge graph. Provides import relationships, source structure, security findings, ownership, and cross-project context, so DependencyIQ understands not just what exists but how it's used.
  • GitLab Duo Agent Platform — Custom Agents, an ambient Custom Flow, and an Agent Skill. Conversational when you want to drive; fully autonomous when you don't.
  • GitLab CI/CD — orchestrates analysis, scoring, remediation, verification testing, MR creation, and dashboard publishing. Every recommendation is validated by the same pipeline that ships the software. The Verify stage even reads the MR's own pipeline and self-heals common failures.
  • OSV-Scanner — multi-ecosystem vulnerability detection (the what's vulnerable, kept separate from Orbit's what's reachable).

🏗️ Architecture

                         OSV-Scanner  ──►  vulnerabilities (npm/PyPI/Go/Maven)
                              │
                              ▼
                     Dependency Discovery
                              │
                              ▼
                    GitLab Orbit Analysis ──► reachability · exposure · usage · blast radius
                              │
                              ▼
                     Risk Scoring Engine  ──► contextual 0–100 score
                              │
                              ▼
                     Remediation Planner  ──► upgrade · override · remove
                              │
                              ▼
            CI Validation (tests + pipeline) ──► proof nothing broke
                              │
                              ▼
              Merge Request (opened, never merged) + Issue + Report

Five surfaces · one engine · three sources of truth (OSV for CVEs, Orbit for blast radius, the GitLab API for MRs/issues/pipelines).


📊 Risk scoring

Rather than trusting CVSS alone, DependencyIQ fuses severity with repository context into a transparent weighted sum:

$$ \text{Score} = \frac{\text{CVSS}}{10}\times 45 \;+\; \text{Exposure}\times 35 \;+\; \text{Usage}\times 10 \;-\; \text{TestCoverage}\times 10 $$

Where each term contributes:

  • \( \frac{\text{CVSS}}{10}\times 45 \) — raw severity, straight from the CVE
  • \( \text{Exposure}\times 35 \) — GitLab Orbit blast radius (real importers / reachability)
  • \( \text{Usage}\times 10 \) — how many files import it
  • \( -\,\text{TestCoverage}\times 10 \) — discount when that usage is test-only

Scaled to 0–100, then bucketed: URGENT ≥ 80 · HIGH ≥ 50 · MEDIUM ≥ 20 · LOW < 20.

Two rules make it trustworthy:

  1. No hidden multipliers — every contribution is shown on the dashboard and sums to the total.
  2. Exposure is 0 when Orbit is unavailable — the score degrades to severity-only and says so, rather than faking a number.

🧪 A real run

Triggered from a single issue mention, fully autonomous:

Stage Result
Discover js-yaml 3.14.2 — quadratic-complexity DoS, CVSS 5.3
Orbit blast radius 2 files import it (validate-config, configLoader), not API-reachable → contextual risk 32/100 (MEDIUM), not a blind high
Plan Zero source changes needed — both call sites already use the safe API
Remediate Transitive — no direct line to bump → applied an overrides fix, opened a merge request
Verify 250/250 tests pass (proof nothing broke); pipeline checked → NOT BLOCKED
Track / Report MR note, a follow-up issue for one dev-only residual, and a summary posted back on the triggering issue

From a one-line request to a verified, ready-to-merge fix — with the human still owning the merge.


🧗 Challenges we faced

The hard part wasn't the scanner. It was building a system that stays trustworthy when information is incomplete, and that fixes safely rather than just flagging.

  • Honest degradation. When Orbit can't answer, the system reports missing context instead of inventing confidence. That's more code and more discipline than a happy path — but it's the only acceptable behavior for security tooling.
  • Version-aware dependency resolution. A remediation run once entered a loop trying to "fix" a transitive vulnerable package that also existed as a safe direct dependency elsewhere. The package name matched; the vulnerable version didn't. The fix required analyzing the whole lockfile by version, not by name — and choosing a scoped override instead of a flat one (which npm rejects with EOVERRIDE).
  • Transitive fixes have no single answer. npm overrides, Maven <dependencyManagement>, pip constraints, Go's MVS — each ecosystem needed its own safe mechanism so a transitive vulnerability still produces a real, committable fix.
  • Autonomous reliability. Multi-stage LLM agents are non-deterministic; we hardened the Flow with explicit stage hand-offs, anti-loop guards, a CI self-heal step, and a strict "verify's verdict is binding" rule so downstream stages never overstate success.

🎓 What we learned

Software supply-chain security is fundamentally a graph problem. Detection is largely solved; relationships are not — which packages are used, which paths are reachable, which systems are exposed, which fixes are safe. GitLab Orbit provides exactly that context, and combining it with Duo Agents and CI-validated remediation turns vulnerability management from alert triage into informed decision-making. And above all: a security tool is only valuable if developers trust its conclusions — so honesty has to be engineered in, everywhere.


🔮 What's next

  • Call-path reachability. Move from "which files import it" to "is the vulnerable function actually invoked." Orbit already stores CALLS edges and Definition nodes — the data is there to traverse.
  • Ownership-aware routing. Use Orbit's ownership graph to auto-assign each remediation to the team that owns the affected code.
  • Policy & SLAs. Let a security org define remediation policy ("URGENT in public-API code → MR within 24h") and track adherence.
  • Org-wide posture over time. Trend dependency risk across a group, so leadership sees the curve, not a snapshot.

🧰 Built With

gitlab · gitlab-orbit · gitlab-duo-agent-platform · gitlab-ci-cd · gitlab-pages · mcp · osv-scanner · node.js · javascript · npm


💡 Why DependencyIQ matters

Security teams already know how to find vulnerabilities. What they need is help deciding which ones deserve attention — and removing them safely without breaking the build. DependencyIQ bridges that gap. It turns dependency alerts into dependency intelligence, and GitLab Orbit's knowledge graph into actionable security decisions.

Because severity isn't priority. Context is.

Built With

Share this project:

Updates