Safeguard
Open Source Security

How Snyk decides whether an automatic PR proposes a minor...

A mechanical walkthrough of the semver logic behind Snyk's automatic fix PRs — how it picks target versions and decides between patch, minor, and major bumps.

Vikram Iyer
Security Researcher
7 min read

When Snyk opens an automatic pull request to fix a vulnerable dependency, the PR title tells you a lot before you even open the diff: is this a quiet patch bump, or a major version jump that could break your build? That distinction isn't cosmetic — it determines how much review the PR deserves and how quickly it should merge. Snyk's remediation engine makes this call using the same semantic versioning rules your package manager already understands, applied to the gap between the version you're running and the version Snyk's vulnerability database says actually contains the fix. Along the way it has to handle edge cases most engineers never think about: packages still on major version zero, transitive dependencies buried three levels deep, and manifests with semver ranges that may or may not already cover the fixed version. This post walks through the mechanics publicly documented by Snyk, using real-world examples to show how a fix request becomes a patch, minor, or major label.

What actually decides whether a Snyk fix PR is a patch, minor, or major bump?

The label comes from a straightforward semver diff between the currently installed version and the lowest version in Snyk's vulnerability database that resolves the issue — not from any judgment call about how risky the code change looks. Semantic versioning defines the three positions in a version string as MAJOR.MINOR.PATCH, and each has a contractual meaning: patch increments are supposed to be bug fixes only, minor increments add backward-compatible functionality, and major increments signal that backward compatibility is not guaranteed. Snyk's remediation logic reads the current and target versions, compares them digit by digit, and reports whichever position changed. If lodash is pinned at 4.17.4 and the database shows the prototype-pollution fix (CVE-2020-8203) landed in 4.17.19, both are 4.17.x — the major and minor digits are identical, so the diff is purely at the patch level, and the PR is scoped as a patch upgrade. If the fix instead requires jumping from 4.x to 5.x, the same arithmetic produces a major label instead, regardless of how small the actual code change turns out to be.

How does Snyk choose the target version instead of just jumping to the latest release?

Snyk targets the lowest version that resolves the known vulnerability, not whatever the package's latest tag happens to be, because the goal is a fix with minimal collateral change. Snyk's vulnerability database tracks the specific version ranges affected by each advisory and the version in which a fix was published upstream. When it builds a remediation PR, it looks up that fix version rather than defaulting to "latest," which is why you'll often see Snyk propose something like 4.17.19 for lodash instead of whatever the newest 4.17.x release is at the time. This matters for the bump-type decision: picking the minimum viable fix version keeps the semver diff as small as mathematically possible, so a vulnerability that was introduced and fixed entirely within a single minor line stays a patch-level PR instead of getting inflated into a minor or major one just because a newer release happened to exist.

Why do major version bumps get extra warnings in Snyk's pull requests?

Major bumps carry an explicit compatibility warning because the semver specification itself defines a major increment as license to break the public API. Under semver's own rules (section 8 of the spec), once the major version changes, consumers have no contractual guarantee that their existing code will keep working — function signatures can change, behavior can shift, entire modules can disappear. Snyk's fix PRs surface this distinction directly in the PR body and labeling, calling out that the change is a major upgrade so reviewers don't mistake it for a routine dependency bump. This is also where a project's own test suite becomes load-bearing: a patch-level PR is asserting "nothing observable changed," while a major-level PR is explicitly not making that promise, which is why teams commonly gate major-bump PRs behind full CI runs and manual review rather than auto-merging them the way they might a patch.

Does Snyk treat packages still on major version zero differently?

Yes, and it has to, because semver itself carves out 0.x releases as a special case: version 0.y.z means the package is in initial development and "anything MAY change at any time," so there's no stable public API to protect yet. A jump from 0.4.2 to 0.5.0 looks like a "minor" bump by digit position, but under the spec it carries the same no-guarantees weight as a major bump on a 1.x-or-later package. This is a real-world edge case in the ecosystem — minimist's CVE-2021-44906 prototype-pollution fix, for example, only landed in 1.2.6, but plenty of vulnerable installs in the wild were still sitting on 0.0.x or early 1.x lines, meaning the actual upgrade path for some consumers crossed both the 0-to-1 major boundary and additional minor increments in a single remediation. Any tool computing bump severity off raw version numbers has to account for the fact that 0.x packages don't play by the same stability rules as 1.x-and-above ones, and Snyk's documented remediation guidance reflects that same semver-spec nuance.

How does Snyk handle transitive dependencies without forcing an unnecessary bump on your direct dependency?

Where the ecosystem supports it, Snyk prefers pinning or overriding the vulnerable transitive package directly rather than forcing an upgrade of the direct dependency that pulled it in. In npm/yarn projects this typically takes the form of an overrides or resolutions entry in package.json that pins the nested package to a fixed version without touching the semver range you declared for your direct dependency at all. That's a meaningfully different remediation shape than a direct-dependency bump: your top-level package.json range for, say, express doesn't change, only the resolved version of whatever vulnerable package it depends on three levels down gets pinned. When the ecosystem or dependency graph doesn't allow clean pinning of a transitive package, Snyk falls back to proposing an upgrade of the direct dependency to a version that itself pulls in the fixed transitive version — and that fallback path is exactly where you're more likely to see a minor or major label appear, because you're now bound by whatever version bump the direct dependency's maintainers chose when they bumped their own vulnerable sub-dependency.

Can engineering teams control which bump types Snyk is allowed to open PRs for?

Yes — Snyk exposes remediation and PR settings at the project and organization level that let teams limit automatic PRs to lower-risk upgrade types and require more scrutiny before major-version PRs get created or merged. Teams that want a hands-off patch pipeline but manual review for anything riskier can configure that split rather than treating every Snyk PR the same way. This matters operationally: a queue that mixes silent patch bumps with major-version rewrites trains reviewers to treat every green checkmark the same way, and that habit is exactly what lets a real breaking change slip through on the day someone's paying less attention. Separating the auto-merge lane from the manual-review lane by bump type is a low-effort way to keep the signal meaningful.

How Safeguard Helps

The semver label on a fix PR tells you about API compatibility risk — it doesn't tell you whether the package you're upgrading to is itself trustworthy, or whether an "automatic PR just merged" event across dozens of repositories represents your actual current exposure. Safeguard sits alongside tools like Snyk in the software supply chain and gives security teams a consolidated view of what dependency changes are actually moving through the org: which fix PRs (patch, minor, or major) have merged, which are still open and aging, and which repositories quietly opted out of auto-remediation altogether. Because Safeguard tracks provenance and integrity signals on top of version metadata, it can flag when an upgrade path — even a "safe" patch-level one by semver's definition — introduces a package version with anomalous publish behavior, a maintainer account change, or other supply-chain red flags that a pure version-number diff can't see. For teams running Snyk, GitHub Dependabot, or similar tools across many repos, that combined view turns "a PR bumped a version" into "here's what actually changed in our exposure," which is the harder question semver labels alone were never designed to answer.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.