The most common mistake I see when teams add security gates to their CI/CD pipeline is also the most predictable one: they configure the gate to block on every finding from their scanner, and within two sprints the gate is either disabled or perpetually bypassed. Alert fatigue in the queue becomes gate fatigue at the pipeline. The problem is not that security gates are a bad idea — they are essential. The problem is which signal you use to trigger them.
Why Blocking on Raw SAST Output Fails
A SAST scanner running on a typical cloud-native service produces thousands of findings per scan. Many of those findings are real vulnerabilities. Most are in code paths that are never executed at runtime. When your pipeline gate says "block the merge if any HIGH or CRITICAL finding exists," you are effectively saying "block the merge if your code has dependencies" — because almost every non-trivial dependency tree contains at least one HIGH-severity CVE at any given point in time.
What follows is predictable. Engineers learn that the security gate will always fail, so they look for the bypass. Some teams add a blanket exception list that grows without review. Others add a flag that marks the current findings as "accepted" and disables the gate for the affected files. The gate still runs — it just never actually blocks anything anymore, which is the worst possible outcome. The security theater is intact while the actual security posture has regressed.
We've tracked this pattern with engineering teams we work with across the US. Teams that use raw CVE count as their gate signal have an average gate bypass rate of 43% within 90 days of initial deployment. Teams that switch to reachability-filtered signal drop to under 8% bypass rate. The difference is not discipline — it is whether the gate is blocking on signal engineers believe is real.
The Right Signal: Runtime Reachability Score
The gate signal that works is the runtime reachability score — a per-finding metric that combines whether the vulnerable code path is actually reachable at runtime with the CVSSv3 base score and exploitability metadata from the CISA KEV catalog. Here is how the scoring works in practice:
- A CVE with a CVSS score of 9.8 in a library that is never called from any live request path gets a reachability score of 2–3. It appears in the suppressed queue with a documented reason. It does not block the merge.
- The same CVE in a library that is called on every authenticated API request gets a reachability score of 8–9. It blocks the merge unless an exception is explicitly recorded.
- A CVE with CVSS score of 6.5 in a function on a critical data processing path — and listed in the CISA KEV catalog as actively exploited — gets elevated to a gate-blocking finding regardless of its base score.
This scoring model means the gate fires on fewer findings, but the findings it does block on are genuinely worth blocking on. Engineers stop bypassing the gate because the block is defensible — they can look at the finding, see the call path, and understand why this specific vulnerability in this specific context requires remediation before merge.
Setting Up Gates That Actually Block
Gate configuration starts with a policy decision: what is the minimum reachability score at which a finding blocks a merge? We recommend starting conservative — block on reachability score ≥ 7 for CRITICAL-severity CVEs, and ≥ 8 for HIGH — and tightening from there as your team's signal fidelity improves with more runtime data.
Here is a minimal Runtimekindle gate configuration in YAML for a GitHub Actions workflow:
- name: Runtimekindle Security Gate
uses: runtimekindle/gate-action@v2
with:
fail_on_reachability: 7
fail_on_severity: CRITICAL
kev_override: true # CISA KEV findings always block regardless of score
suppress_unreachable: true # Unreachable findings go to suppressed queue, not failure
report_format: sarif # Uploads to GitHub Security tab
The kev_override: true flag is important. CISA's Known Exploited Vulnerabilities catalog is updated regularly with CVEs that have confirmed active exploitation in the wild. A CVE in that catalog should be treated as a higher-priority signal regardless of theoretical reachability score — attackers have already demonstrated they know how to reach the vulnerable code in real environments.
Handling Legacy Code and Accepted Risk
No pipeline gate design survives contact with a legacy codebase without an exception mechanism. The exception process is where gate discipline either holds or breaks down. Here is what the exception process should look like:
- Exception requests are explicit in code. A comment block in the affected file or a YAML exception record in the repository — not a checkbox in a third-party tool — documents the exception. This means exceptions are visible in code review and auditable in git history.
- Every exception has an expiry. Exceptions expire after 30 days by default. An expired exception causes the finding to re-enter the active queue at its original priority. This forces re-evaluation rather than silent accumulation.
- Exception reason is required. "We are aware of this finding" is not a valid exception reason. "This function is not called in production; confirmed by Runtimekindle call-graph as of 2026-03-10; monitored for reachability changes" is valid. The reason must reference the evidence that justifies the exception.
This exception process is deliberately friction-inducing. That friction is the point. A security exception should require more effort than just fixing the vulnerability. For genuinely unreachable code, the exception should document why the code cannot be removed — not just why the CVE is theoretically acceptable.
Managing Gate Latency
One of the practical objections to security gates is that they add scan time to the CI pipeline. This is a real concern. A scanner that adds 10 minutes to every commit check on a team making 50 commits per day creates 8+ hours of cumulative added pipeline time daily — meaningful at any engineering org.
The way to manage gate latency is incremental scanning. Runtimekindle's pipeline integration supports incremental mode: on a feature branch commit, only the changed files and their dependency graph are re-scanned and re-scored. A full repo scan runs on merge to main (or on a configurable schedule). Incremental scans for typical feature branch commits complete in 45–90 seconds rather than 8–12 minutes for a full scan. That is within the acceptable range for most CI workflows.
The reachability call-graph is cached and updated asynchronously from the staging environment, so the incremental scan has current reachability data without needing to re-instrument the application on every commit. The call-graph refresh cycle is configurable — most teams update every 4–6 hours in staging, which provides current-enough data for gate decisions without adding synchronous latency to the pipeline.
Measuring Gate Effectiveness Over Time
A security gate is only useful if it is actually blocking genuine risk and not generating bypass incentives. Here are the metrics worth tracking for gate health:
- Gate trigger rate: What percentage of commits trigger a gate block? If it is above 15–20%, your thresholds may be too aggressive and you are generating bypass pressure. Below 2%, check whether the gate is actually running.
- Exception accumulation rate: How many new exceptions are added per sprint? A growing exception list that never shrinks is a sign the exception process is functioning as a bypass mechanism rather than a risk management tool.
- Time-to-remediate for gate-blocked findings: Gate-blocked findings should be resolved faster than unblocked findings — because they are blocking merges. If remediation time for gate-blocked findings is longer than for non-blocked ones, the gate is being bypassed rather than triggering action.
- Escaped vulnerabilities rate: How many security incidents or pen-test findings per quarter involve vulnerabilities that passed through the gate? This is the ground-truth measure of gate effectiveness.
The Organizational Change Behind the Technical Change
The technical configuration of a security gate is the easy part. The harder part is the organizational change required to make engineers treat security findings as their responsibility rather than a security team artifact that lands in their ticket queue.
In our experience, the teams that make DevSecOps work share one characteristic: security findings generated by the pipeline are owned by the engineer who wrote the code, not by a central security team that triages on their behalf. The pipeline gate surfaces the finding at the point where the engineer is already thinking about the code. That is the moment when remediation is cheapest — before the code has merged, before it has been deployed, before the context has faded from memory.
Security gates designed around reachability-filtered signal — blocking only on findings that engineers can verify are real, on code paths they can see in context — make this ownership model viable. Gates designed around exhaustive scanner output make it untenable, because no engineer can own a queue of 4,000 findings while also shipping software.
The choice between those two approaches is not just a technical configuration decision. It is a decision about whether your security program is optimizing for coverage counts or for actual risk reduction. Only one of those produces outcomes worth measuring.