CI/CD security gates that engineers do not bypass
Most security teams have lived through this. A scanner is added to the pipeline with every rule set to block. On day one it fails every build in the organisation, because the codebase already has hundreds of findings. By the end of the week there is an urgent request to make the step non-blocking "just for now". A month later nobody looks at its output.
A CI/CD security gate is only useful if it stays switched on. This post covers how to design one that does.
What a security gate is for
A gate is a pipeline step that can stop a change from merging or deploying when it introduces a security problem. It usually combines several kinds of scanning:
- Static analysis (SAST) of application source, for issues such as injection, unsafe deserialisation and hard-coded credentials.
- Software composition analysis (SCA) of dependencies, including transitive ones, for known vulnerabilities.
- IaC scanning of Terraform, CloudFormation, Helm and Kubernetes manifests, for misconfiguration before it is deployed.
- Secret detection, for keys and tokens committed to source or pipeline configuration.
- In some pipelines, dynamic testing (DAST) of a running build in a test environment.
The gate's job is narrow: stop new problems from entering. It is not the place to fix every problem that already exists.
Why gates get bypassed
The reasons are predictable:
- They block on old findings. An engineer changing one line is blocked by an issue introduced three years ago in a file they did not touch.
- They are noisy. A dependency scan that returns hundreds of findings ranked only by CVSS gives no way to tell which ones matter.
- The output is unreadable. A link to an external dashboard, rather than the file, line and reason in the pull request.
- There is no exception path. When a finding is a false positive or an accepted risk, the only way through is to disable the step.
- They are slow. A gate that adds a long wait to every pull request gets moved to a nightly job, where it no longer gates anything.
How teams handle it today
The common patterns, roughly in order of maturity:
- Report-only scanning, with results in a dashboard nobody checks.
- Blocking on critical severity only, which helps but still blocks on pre-existing criticals.
- Baseline-and-diff, where existing findings are recorded as a baseline and only new findings block.
- Context-aware gating, where the decision also considers whether the affected code or workload is reachable and exposed in production.
Most teams get real value from moving from step 2 to step 3. Step 4 is where noise drops further.
A checklist for a gate that stays on
Scope the decision to the change
- Block only on findings introduced by this change. Pre-existing findings go to a backlog with owners and a schedule.
- Keep the baseline honest: findings in the baseline still need tracking and fixing, just not in this pull request.
Start small, then tighten
- Begin with a short list of blocking rules: high-confidence, high-impact issues such as committed secrets, critical injection flaws, and public storage or open admin ports in IaC.
- Run the rest in report-only mode and promote rules to blocking once their false positive rate is known.
- Allow different policies per repository or branch where risk genuinely differs, with the security team owning the policy.
Make the output actionable
- Show findings in the pull request, with file, line, rule and a short explanation.
- Include a compliant example or a suggested fix where possible.
- For dependency findings, show the version that resolves the issue.
Add context to dependency findings
- Prefer reachability over presence: is the vulnerable function actually called by your code?
- Consider exploitation signals such as EPSS and the CISA Known Exploited Vulnerabilities list alongside CVSS.
- Consider runtime context: is the workload that ships this package internet-reachable, and what identity does it run as?
Provide an exception path
- Allow a finding to be marked as a false positive or accepted risk, with a reason and an approver.
- Give exceptions an expiry date so they are reviewed.
- Keep exceptions visible to the security team, not hidden.
Keep it fast
- Run incremental scans on the changed files where the scanner supports it.
- Run heavier scans, such as full DAST, on a schedule or before release, not on every commit.
Measure the gate itself
- Track new findings introduced per week, findings blocked, exceptions granted, and time to fix the backlog.
- If exceptions climb, the policy is too strict or the rules are noisy. Fix the policy rather than letting the gate be bypassed.
How Onam approaches it
Onam's Code Security engine brings static analysis, dependency analysis, IaC checks and secret detection into the same platform as its cloud posture. Static analysis keeps proven security issues apart from pattern-match hotspots, and dependency findings are ranked by EPSS and CISA KEV as well as CVSS — two ways of keeping a gate from firing on noise.
On gating, Onam is deliberately conservative: a scan reports its findings and nothing fails on its own. Onam has no CI plugin today; a pipeline step calls the scan API, reads the findings and decides (CI usage). Scans cover the whole branch rather than only new findings, so the practical route to the delta-gating pattern described above is to start in report-only mode, work the backlog down, and turn your gate on once the baseline is small.
For SAST findings, AI Code Fix can rewrite the affected files and push them to a separate branch for your team to review; nothing merges itself.
Request a demo to see the gate on one of your repositories.