GitGuardian's State of Secrets Sprawl 2025 report counted 23.8 million secrets leaked on public GitHub commits in 2024 — up 25% year over year — and found that roughly 70% of secrets leaked back in 2022 were still active and unrevoked when the report was published. That single stat captures the core failure mode of most security-automation programs: teams bolt a scanner onto CI, it fires thousands of findings, nobody triages them, and the handful of real, exploitable issues drown in the noise. The fix isn't running more tools — it's running the right check at the right stage, and tuning each one so a BLOCK means something. CISA's Known Exploited Vulnerabilities (KEV) catalog and FIRST.org's EPSS score exist for exactly this reason: they let you separate "technically vulnerable" from "actively being exploited right now," which raw CVSS severity alone cannot do. This post walks through a layered gate model — IDE, pre-commit, CI, pre-merge, registry/pre-deploy, and runtime — and the concrete noise-reduction techniques (reachability analysis, secret verification, cross-scanner dedup) that make each stage worth trusting rather than muting.
Where should the first gate actually run?
The first gate should run in the IDE or a local pre-commit/pre-push hook, because that's the cheapest point in the entire SDLC to fix a defect — the code is still open in the developer's editor and no one else has seen it yet. A pre-push hook scanning for secrets, for instance, catches a hardcoded AWS key before it ever reaches a shared branch, which matters given GitGuardian's finding that generic, non-issuer-specific patterns (JWTs, private keys, connection strings) made up 58% of all leaks in its 2025 dataset — these are exactly the patterns a local hook can catch without needing network access to verify. The tradeoff is coverage: local hooks only see the diff a developer is about to push, not the full repository history or cross-file data flow, so they should run fast, narrow checks (secrets, obvious hardcoded credentials, dependency confusion on new imports) and defer deeper analysis — full SAST dataflow tracing, transitive SCA resolution — to CI, where compute budget is larger and the check can afford to take minutes instead of seconds.
What belongs in the CI build stage versus the pre-merge check?
CI build-stage gates should run the full-depth scanners — SAST with source-to-sink taint tracing, full-graph SCA resolution including transitive dependencies, and a complete secrets sweep — because CI has the compute budget and network access (for live secret verification) that a local hook doesn't. The pre-merge PR check is a narrower, faster derivative of that same data: it should surface new findings introduced by the diff, not re-litigate the entire existing findings backlog on every pull request. This distinction matters for adoption — a PR check that blocks on pre-existing debt no one asked the author to fix trains developers to treat the gate as noise and merge around it. A clean split is: CI runs the deep scan and persists results to a findings store; the PR check queries that store for findings whose file/line ranges intersect the diff, and blocks only on those that meet policy (e.g., any CWE-89 or CWE-502 finding, or any CISA KEV-listed CVE in a changed dependency).
How do EPSS and KEV change what "block" means?
EPSS and KEV change "block" from a static severity threshold into a dynamic, exploitation-aware signal. CVSS answers "how bad would this be if exploited" — a fixed number tied to the vulnerability itself — while EPSS, maintained by FIRST.org and updated daily, answers "how likely is this to be exploited in the next 30 days," a probability between 0 and 1 that shifts as real-world attacker activity changes. FIRST.org explicitly designed EPSS to complement CVSS, not replace it: a CVSS 9.8 vulnerability with a near-zero EPSS score in an unreachable code path is a very different risk than a CVSS 7.5 with a high EPSS score that's also on CISA's KEV catalog, which CISA updates with new confirmed-exploited CVEs on a near-weekly cadence. A mature CI gate blocks on "critical severity AND (KEV-listed OR high EPSS) AND reachable," not on severity alone — which is also the shape of the built-in "block CVEs on the KEV list in production" guardrail pattern used in policy-as-code enforcement today.
What actually reduces false positives in SCA and secrets scanning?
Reachability analysis and live-issuer verification are the two techniques with the most evidence behind them. For SCA, a scanner that only matches manifest versions against a CVE database reports every vulnerable package present, whether or not your code calls the vulnerable function — reachability analysis builds a call graph from your entry points and checks whether execution can actually reach the flagged code path, which is what lets teams stop treating every dependency CVE as equally urgent. For secrets, the equivalent technique is verification: rather than alerting on every regex match, a scanner makes a low-privilege, read-only API call to the issuing service — AWS's sts:GetCallerIdentity, GitHub's /user endpoint, Slack's auth.test — to confirm the credential is actually live before marking it verified. Given GitGuardian's finding that most 2022-vintage leaked secrets were still active in 2025, verification is what turns "we have 400 secret findings" into "we have 12 live credentials to revoke today," and lets a team calibrate severity (critical for a verified admin-scoped credential, low for an unverified generic pattern) instead of treating every hit the same.
Where do pre-deploy and runtime gates fit in?
Pre-deploy (registry/admission) and runtime gates exist because a clean CI run doesn't guarantee a clean deployment — a new KEV-listed CVE can be published, or a policy can change, days or weeks after an image passed CI and sat in a registry. A registry or admission-control gate re-evaluates the image's SBOM and vulnerability set at the moment of push or Kubernetes admission, catching drift between build time and deploy time, and can additionally enforce supply-chain requirements CI checks alone can't — a valid Cosign or Notation signature, an SBOM attestation less than 90 days old, SLSA provenance level. Runtime gates go one step further, watching for behavioral drift from the approved baseline (an admission-approved container that starts making unexpected outbound connections, for example) via eBPF-based collection — catching the case where the image itself was fine but something changed after the container started running. Each of these stages should reuse the same findings model and policy language as CI, not a separate parallel system, or teams end up maintaining three inconsistent definitions of "critical."
How Safeguard helps
Safeguard implements this layered model as six enforcement points — IDE, commit, CI, registry, admission, and runtime — evaluated against a single policy-as-code document that combines SBOM, vulnerability, license, signature, provenance, and reachability data, with effects of BLOCK, WARN, or AUTO_FIX. SCA findings carry an EPSS/KEV-enriched severity and a reachability verdict so a CVE in dead code doesn't compete for attention with one an attacker can actually reach. Secrets scanning runs three overlapping detection layers — issuer-specific patterns, generic patterns, and entropy-based anomalies — and verifies issuer-pattern findings against the live service (AWS STS, GitHub, Stripe, Slack, and more) before marking them verified, so severity reflects whether a credential is actually exploitable right now, not just whether it matched a regex. AutoTriage deduplicates overlapping findings across SAST, SCA, and secrets into one record — with the standing rule that malware and secret findings are never suppressed by reachability, regardless of how "unreachable" the surrounding code looks — so the CI gate that fires is one your team can actually trust enough to block on.