Safeguard
Open Source Security

How Snyk Open Source's PR checks block merges based on se...

A technical look at how Snyk Open Source's PR checks scan pull requests, compare severity to configured thresholds, and gate merges in CI/CD.

Priya Mehta
DevSecOps Engineer
7 min read

When a developer opens a pull request that bumps a dependency or adds a new package, Snyk Open Source quietly runs a scan against the manifest and lock file changes before a human reviewer even looks at the diff. If that scan turns up a new vulnerability that meets or exceeds a severity level the organization has configured — say, High or Critical — Snyk reports a failing check on the PR. Whether that failing check actually stops the merge button depends on a second, often-overlooked piece of configuration: the repository's branch protection rules. This distinction — Snyk decides pass/fail, GitHub or GitLab decides whether pass/fail matters — is the core mechanic behind what's usually described as "severity gating." Below is a walkthrough of how the threshold is set, what counts as a "new" issue, how CVSS scores map to Snyk's four severity tiers, and where teams typically get the setup wrong.

What does Snyk's PR check actually scan?

Snyk's PR check runs a dependency test against the changes introduced in the pull request, not a full re-scan of the entire repository. When a PR modifies a manifest file (package.json, pom.xml, requirements.txt, go.mod, and similar) or its corresponding lock file, Snyk's integration triggers a snyk test-equivalent scan scoped to that diff. It resolves the dependency tree — including transitive dependencies — and checks each package version against Snyk's vulnerability database. Snyk's documentation notes that scan accuracy depends heavily on lock files being present and committed; without a package-lock.json or yarn.lock, Snyk has to infer version ranges rather than resolve exact transitive versions, which produces less precise results. The output of that scan is posted back to the PR as a check run (via the GitHub App, GitLab integration, Bitbucket, or Azure Repos connector) along with a comment listing the vulnerabilities found, their CVE or Snyk ID, and a suggested fix version if one exists.

How does Snyk decide which severity level blocks the check?

The threshold is a setting, not a hardcoded rule — teams choose it under the SCM integration settings, in a field typically labeled something like "fail PR checks for issues with a severity of X or higher." Snyk classifies vulnerabilities into four tiers — Low, Medium, High, and Critical — derived from the underlying CVSS base score: roughly 0.1–3.9 for Low, 4.0–6.9 for Medium, 7.0–8.9 for High, and 9.0–10.0 for Critical. An organization that sets the threshold to High will see the PR check fail for any newly introduced issue scored 7.0 or above, while a Medium-severity dependency bump sails through with a passing check and a warning comment. Snyk also layers in exploit-maturity and fixability signals through its own Priority Score, a 0–1000 metric that can be used to rank issues beyond the raw CVSS tier, but the PR-blocking threshold itself is configured against the four standard severity levels, not the Priority Score, in the vast majority of documented setups.

Why doesn't a failing Snyk check always stop a merge?

Because Snyk's check is a status signal, not a merge lock, and the two only connect if the repository owner wires them together. In GitHub terms, Snyk posts a "check run" (or commit status, depending on integration version) with a state of success or failure. That state has zero effect on the merge button unless the repository's branch protection rules list that specific check as a "required status check." If a team enables Snyk's PR check but never adds it to branch protection, developers can merge past a red X without any friction — the failing check is informational only. This is one of the most common misconfigurations reported by teams adopting Snyk: the scan runs, the comment appears, the check goes red, and the PR still merges because nobody made the check mandatory in the repo settings. The gating behavior people describe when they say "Snyk blocks merges on severity" is really the combination of two independent controls: Snyk's severity evaluation plus the SCM platform's required-check enforcement.

Does Snyk gate on every vulnerability in the project, or just what the PR introduces?

Only what the PR introduces, or more precisely, what changes between the base branch and the PR branch. Snyk's PR check is a diff-aware scan: it compares the vulnerability set resolved from the base branch's manifest/lock files against the set resolved from the PR branch's version. If a repository already has an existing dependency with a Critical vulnerability sitting untouched on the main branch, opening an unrelated PR does not re-trigger a failure for that pre-existing issue — the check is scoped to newly introduced or newly upgraded packages. This design choice avoids the common alternative failure mode where every single PR in a codebase with legacy vulnerable dependencies would be permanently blocked regardless of what the PR actually changes. It also means teams with a large backlog of existing open-source vulnerabilities can still ship code, while new risk introduced through dependency changes is caught at the point of entry.

Can a specific vulnerability be exempted from the severity gate?

Yes, through ignore policies, and this is usually managed via the .snyk policy file or the Snyk web UI's "ignore" action on a specific issue. When a security or engineering lead reviews a flagged vulnerability and decides it's a false positive, not exploitable in context, or accepted as a temporary risk, they can ignore it with a reason and, in many configurations, an expiration date after which the ignore lapses and the issue reappears in scans. Once ignored, that specific vulnerability ID is excluded from future PR check evaluations for that project, even if it would otherwise cross the severity threshold. This is a project-level or organization-level override mechanism, separate from adjusting the global severity threshold — it targets one specific finding rather than changing what severity blocks merges going forward. License-based policy violations (for example, flagging a newly introduced GPL-licensed package) follow a comparable but distinct policy path, evaluated alongside — not merged into — the vulnerability severity gate.

How Safeguard Helps

Severity-threshold gating on pull requests is a useful first checkpoint, but it's evaluating one signal — a CVSS-derived tier — at one moment in the delivery pipeline, and its effectiveness depends on teams correctly wiring status checks into branch protection in the first place. Safeguard approaches software supply chain risk as a continuous surface rather than a single gate: tracking dependency provenance, build integrity, and package behavior across the entire pipeline, not just the diff visible in a pull request. That matters because severity scores alone don't capture whether a vulnerable function is actually reachable in your call graph, whether a package's publish history shows signs of takeover, or whether a transitive dependency changed maintainers overnight. Safeguard correlates these signals so security teams get context beyond "this CVE is rated High," and can verify that the controls they think are enforced — required checks, branch protections, ignore-policy expirations — are actually configured as intended across every repository, not just the ones someone remembered to set up correctly. For teams relying on PR-level severity gates as their primary control, that continuous verification closes the gap between "the check exists" and "the check is actually protecting the merge."

Never miss an update

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