GitLab tries to auto-fix the transitive-dep problem it keeps quantifying
Tomás Vega
Every direct dependency you add is a promise you can read. Every transitive dependency is a promise you inherited from someone who never met you. Which is why the number GitLab keeps citing is uncomfortable: in a 2025 study of the Maven ecosystem, vulnerabilities reach roughly 63% of latest releases through transitive dependencies, versus 31% through the direct ones you actually picked. This week GitLab pushed a bet on that gap, moving Dependency Scanning Auto-Remediation into beta.
The pitch is straightforward. The scanner already tells you a transitive dep is dragging in a known-vulnerable version. Now the platform tries to close the loop and open the fix for you, instead of dumping another finding into a backlog that nobody has budget to burn down.
What actually shipped
The feature is a beta, opinionated auto-remediation flow for vulnerable dependencies picked up by GitLab's existing dependency scanning. GitLab's framing for why it needs to exist is worth quoting from their own reasoning: AI is writing more code, that code pulls in more dependencies, and application risk goes up in lockstep. Their number for the gap is the Maven figure above: 63% transitive, 31% direct. If you write mostly JVM code, that pair of percentages is the whole business case for automated fixing.
What GitLab has not put in the announcement, and what you should not assume, is that this replaces your review. A beta is a beta. Treat it as a candidate PR generator, not as a merge policy.
Why the transitive number is the hard part
Fixing a direct dependency is boring. You bump the version in your manifest, the resolver picks it up, tests either pass or they don't. If the vuln lives two levels down, none of that is true. You cannot just edit a line. You have to convince the resolver to prefer a fixed version, which usually means one of these:
- Force a version. Maven
dependencyManagement, Gradle constraints,resolutionsinpackage.json,overridesin npm,[tool.uv.constraint-dependencies]and friends. These work until an intermediate library declares an incompatible range and blows up at runtime, not at build time. - Bump the parent. Push the direct dependency to a newer release whose transitive graph pulls the fixed version naturally. Cleaner, but only if the parent has published a fix, and only if the API didn't break.
- Swap the library. The nuclear option. Usually reserved for abandoned upstreams.
A real auto-remediation flow has to pick one of those, generate a diff, and defend it. That is a lot of engineering to hide behind a single "fix" button. Whether GitLab's beta does the first, the second, or a mix is the thing to read carefully in the docs before you turn it loose on main.
Why a CI/CD practitioner should care
The interesting operational shift is not "the scanner opens PRs". Dependabot and Renovate have done that for years. The shift is: does the platform propose a fix for a transitive CVE without asking you to become a build-tool archaeologist?
That is the practitioner value. If your pipeline is already scanning on every merge request, the remediation candidate rides the same lane. You get:
- A review boundary, because the fix arrives as a change you can accept or reject.
- A test signal, because the same pipeline that reported the CVE now runs the tests against the proposed pin.
- An audit trail, because the remediation lives in git history, not in some vendor console.
None of that is magic. It is exactly what "shift left" was supposed to look like before it turned into a slide. It only pays off if the bot's suggestions are correct often enough that engineers stop reflexively closing them.
What to watch out for
Some questions you want answered before you flip this on for a repo that matters:
- Which resolver strategies does it prefer? Version pinning is a different risk profile than a parent bump.
- How does it behave when the fixed version does not exist yet? A bot that opens PRs targeting nonexistent releases is worse than one that stays quiet.
- Does it re-check its own PR after CI runs, or does it walk away? Auto-remediation without regression awareness is a good way to teach reviewers to auto-close everything from the bot.
- What is the blast radius when it is wrong? A merged bad pin can freeze a project on a stale version for months.
Also: the 63% number is Maven. Your risk surface for a Node service or a Go binary is a different shape. The framing generalises, the arithmetic doesn't.
How popular tools handle the same problem
Auto-remediation is a crowded lane. Nobody has fully solved transitive fixes at scale, and every tool trades something.
- Dependabot. Handles direct-dep security updates well, integrates cleanly with GitHub Advanced Security, opens narrowly scoped PRs. Transitive fixes are still weaker; you often end up reading its output and doing the pin yourself. If you live in GitHub and your dependency graph is mostly shallow, this is likely the right default and is a better fit than adding another vendor.
- Renovate. The most flexible of the bunch. Config lets you dictate almost any grouping, schedule and update strategy. The price is that it is a configuration surface all by itself. Powerful, not opinionated.
- Snyk. Prioritises fixes by reachability and exploit signal, which is often what you actually want at 4pm on a Friday. Adds a vendor to your build path and a licence line item.
- Mend. Longer-standing remediation platform with policy controls, aimed at larger orgs with a security team that wants central rules. Heavier to adopt than a bot in a repo.
- GitLab Dependency Scanning Auto-Remediation (beta). The subject of this piece. Interesting if GitLab is already your build platform and you want the remediation candidate to live inside the same merge request that flagged the CVE.
- Buddy. A CI/CD pipeline platform rather than a scanner in its own right; the concrete reason to reach for it is when you want the remediation workflow orchestrated by the same pipeline that runs your build. You wire the scanner of your choice (Snyk, Trivy,
npm audit,osv-scanner) into a pipeline step, run tests on the proposed fix, and only open the PR when the pipeline is green. Rough shape:
- action: "Scan dependencies"
type: "BUILD"
docker_image_name: "aquasec/trivy"
execute_commands:
- "trivy fs --scanners vuln --exit-code 0 --format json -o vulns.json ."
- action: "Propose fix"
type: "BUILD"
execute_commands:
- "./scripts/propose-fix.sh vulns.json"
- "git push origin fix/deps-$CI_COMMIT_SHORT"
That is a build-your-own remediation loop, not a magic fix button. If you want a batteries-included PR generator without wiring, one of the tools above will get you there faster.
The verdict
The right way to read this beta is not "GitLab fixed transitive vulns". It is "GitLab is trying to move the cost of fixing a transitive vuln from an engineer's afternoon to a bot's ten seconds, and eating the false-positive tax in public to see if the math works".
That is a bet worth taking, cautiously. Turn it on for a low-stakes service first. Read the diffs. Reject the ones that would freeze a version, accept the ones that bump cleanly. Watch how it behaves on a resolver you actually understand.
If it holds up, you have removed one of the least fun days of the sprint. If it doesn't, you closed some PRs. Either way, the 63% number is not going anywhere.
Trust the bot. Verify the pin.
Source: GitLab (about.gitlab.com)