Safeguard
Application Security

How Snyk Code's PR and MR checks block merges on newly in...

A mechanical look at how Snyk Code's pull and merge request checks isolate net-new vulnerabilities from pre-existing debt and gate merges on policy.

Aman Khan
AppSec Engineer
7 min read

A pull request sits open with 40 lines changed. Somewhere in that diff, a new call to eval() on user input slips in, or a dependency bump drags in a package with a known deserialization flaw. Most teams find out about issues like this in a security backlog review weeks later, if at all. Snyk Code — Snyk's static application security testing (SAST) engine — is built to catch this at the moment of merge instead, by scanning the pull request (PR) or merge request (MR) diff, comparing the result against the target branch's existing baseline, and applying a configurable policy that can fail the check and block the merge when a genuinely new vulnerability shows up. This post walks through the mechanics publicly documented by Snyk: how the scan triggers, how "new" is distinguished from "pre-existing," what a blocked check actually looks like in GitHub or GitLab, and where teams typically configure the gating rules.

How does Snyk Code trigger a scan on a pull request?

Snyk Code triggers through a source control management (SCM) integration — GitHub, GitLab, Bitbucket, or Azure Repos — that registers a webhook or app on the repository. When a PR or MR is opened, or when new commits are pushed to an open one, the SCM fires an event that Snyk's integration listens for. Snyk then pulls the diff, runs its SAST analysis against the changed files (and enough surrounding context to trace data flow across function boundaries), and posts the result back to the SCM as a status check. On GitHub this shows up as a commit status or a check run tied to the head SHA of the PR; on GitLab it appears as a pipeline status or merge request widget. Because the check is tied to the SCM's native status API, it plugs into whatever merge-blocking mechanism the platform already offers — GitHub branch protection rules or GitLab merge request approval/pipeline rules — rather than requiring a bespoke gate. Re-scans happen automatically on every push to the PR branch, so a developer who force-pushes a fix after an initial failing check gets an updated status without having to manually retrigger anything, and the check result is always tied to the latest commit SHA rather than the PR as a whole.

How does Snyk Code tell a new vulnerability from an existing one?

It does this by diffing scan results against a baseline snapshot of the target branch, not just the files touched in the PR. Snyk Code maintains (or generates on demand) a baseline scan of the branch a PR targets — typically main or develop. When the PR check runs, Snyk compares the set of issues found in the PR branch to the set of issues in that baseline. Any issue present in both is treated as pre-existing technical debt; anything that appears only in the PR branch is classified as newly introduced. This baseline-diffing approach is what lets a repository with, say, 200 pre-existing medium-severity findings still pass PR checks on day one — the check isn't asking "is this codebase clean," it's asking "did this specific change make things worse." That distinction is what makes the gate usable in large, older codebases that could never realistically hit zero findings before the day the PR checks were switched on.

What actually happens when a check fails?

When Snyk classifies at least one finding as newly introduced and that finding meets the configured severity threshold, it reports the check as failed rather than passed, and the PR/MR page shows the failing check alongside details of the flagged issue — file, line range, vulnerability type (for example, an injection or path-traversal pattern), and a suggested fix where Snyk Code's fix-suggestion feature has one available. If the repository's branch protection settings (GitHub) or merge checks/approval rules (GitLab) are configured to require that status check to pass, the merge button is disabled until the developer either remediates the flagged code, provides a documented exception, or a reviewer with sufficient permissions overrides the requirement. Snyk does not itself revert or block commits at the git level — it reports pass/fail status through the SCM's existing API, and the SCM's own branch protection enforces the block. This matters because it means the "gate" only exists if a team has actually turned on the corresponding required-status-check setting; the scan running and the merge being blocked are two separate configuration steps.

Can teams control which severities actually block a merge?

Yes, through policy settings in the Snyk organization or project configuration rather than through the SCM. Snyk lets teams set a severity threshold — for example, only fail PR checks on high or critical findings, while medium and low findings are still surfaced as informational comments but don't block the merge. This is typically configured per project or per organization in the Snyk web console, under the integration's PR check settings, and can also account for exploit maturity or fixability signals so that a theoretical low-severity issue with no known proof-of-concept doesn't hold up a release the same way an actively exploited pattern would. Teams can also scope checks to specific branches (for example, only enforcing hard blocks on PRs targeting a production release branch) while running checks in report-only mode elsewhere. This tunability is what separates a gate that developers route around by finding workarounds from one that survives contact with a real engineering org.

Does this replace a full repository scan?

No — PR/MR checks are a complement to, not a replacement for, scheduled or on-demand full-repository scans. The diff-based PR check is deliberately scoped to the changed code and its baseline comparison to keep feedback fast enough to fit inside a normal review cycle, often returning results in well under a minute for typical PR sizes. A full scan of the entire repository, run on a schedule or triggered manually, is what surfaces the complete picture of existing vulnerabilities, including ones introduced before PR checks were enabled or found through updated detection rules after the fact. Organizations commonly run both: full scans to build and refresh the baseline and drive backlog remediation, and PR checks to make sure that baseline doesn't quietly grow worse with every merge. Snyk also supports scheduled re-tests of monitored projects independent of any PR activity, so a project that goes quiet for a month still gets re-evaluated against newly published rules or updated vulnerability data rather than only refreshing whenever the next PR happens to open.

How Safeguard Helps

Point-in-time PR gates like Snyk Code's checks are effective at stopping a specific class of problem — a known vulnerability pattern landing in a diff — but the guarantee they provide is only as strong as the SCM configuration behind it: which branches require the status check, who can override it, and whether every repository in the org actually has it turned on consistently. Safeguard is built to give security and platform teams visibility into that layer across an entire GitHub or GitLab organization: which repositories have required status checks configured, where branch protection has gaps or exceptions, and whether SAST and SCA gating policies are applied uniformly rather than repo-by-repo. Rather than replacing the scanning engine itself, Safeguard helps teams answer the harder organizational question — is the gate we think we have actually enforced everywhere it needs to be — and keeps that posture auditable for SOC 2 and other compliance reviews. For teams already running Snyk Code, that visibility closes the gap between "we have a policy" and "the policy is actually blocking merges on every repository it should be."

Never miss an update

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