What should actually fail a build?
Very little, and the list is shorter than most policies assume. A gate is a promise that every future release will stop until a human intervenes, which means the only rules that belong in one are those where stopping is clearly the right answer every time. Everything else belongs in a backlog with an owner and a date. Getting this boundary wrong is the most common way a security programme loses the consent of the teams it depends on.
What makes a rule safe to gate on?
Three properties, and a rule needs all three. It must be unambiguous, so that a hit is a fact rather than an opinion about risk. It must be actionable by the person the gate interrupts, so the developer staring at a red pipeline has something they can do in the next hour. And the fix must exist, because a gate on a problem with no available remedy is just a stopped release.
Severity fails the second and third tests routinely, which is why gating on severity alone is the classic error. A critical finding in a transitive dependency with no patched version is unfixable by the developer who happened to be merging a copy change. The gate is technically correct and operationally useless, and within a fortnight somebody will add a bypass to get a release out.
Test any proposed rule against those three properties before it goes into a policy document. If it fails one, you can still report the finding, still track it and still hold someone to a deadline. You just cannot make it stop a build, because a control that gets routinely overridden produces a record suggesting a check happened when it did not.
Which rules pass the test?
A small and stable set. Credentials or private keys detected in the code or in an image layer, because the response is defined and immediate. Infrastructure definitions that violate an objective policy, such as a storage bucket with public read or a security group open to the world on an administrative port. Containers configured to run as root without a recorded exception. A missing or invalid artefact signature at deploy. A dependency finding that is both above your agreed threshold and has a fixed version available.
Notice what these have in common: each names a specific change to a specific file, and none asks the developer to form a view about exploitability. That is the shape of a gateable rule. The misconfiguration rules are the most valuable of the group and the most under-used, because misconfiguration is where a large share of real cloud incidents originates and the rules are objective enough to survive an argument.
The one that surprises people is signature verification at deploy. It is the cheapest gate to run, it never produces a false positive from a vulnerability database, and it is what makes every upstream check meaningful, because a pipeline that scans carefully and then deploys anything has verified nothing.
| Rule | Gate or report | Why | Who can override |
|---|---|---|---|
| Secret or private key detected | Gate, hard | Unambiguous, and the response is rotation not debate | Nobody, rotate and rebuild |
| Public storage bucket, open administrative port | Gate | Objective, names a line in a definition, fix is minutes | Security, with a recorded exception |
| Container runs as root, writable root filesystem | Gate with an exception mechanism | Fix is a manifest change, exceptions are legitimate but rare | Service owner, expiring |
| Missing or invalid artefact signature at deploy | Gate, hard | Cheap, deterministic, and it makes upstream checks matter | Nobody |
| Dependency finding with a fixed version available | Gate above an agreed threshold | Actionable, the remedy is a version bump | Service owner, time-boxed |
| Dependency finding with no fix available | Report and track | Developer can do nothing, so a gate only teaches bypassing | Not applicable |
| Static analysis finding on pre-existing code | Report, ratchet on new code only | Not caused by this change, will block unrelated work | Not applicable |
How do you gate without blocking every legacy problem?
Baseline the existing findings and gate only on what the current change introduces. Every serious static analysis and dependency tool supports some form of this, whether it is called a baseline, a ratchet or new-code-only mode. Adopting it is what makes a gate possible on a codebase with years of history, and refusing it is why so many teams conclude that gating is impractical.
The mechanism matters more than the label. Keep the baseline in the repository, reviewable in a pull request, and give it a direction of travel: the count may go down in any change and may not go up. A baseline nobody ever reduces is a permanent amnesty.
The same idea applies to container images. Gate on what this build introduces relative to the base image, and handle inherited base image findings through a scheduled rebuild rather than by interrupting a developer who added a logging field.
What does a break-glass path look like?
Available, loud and time-limited. Every gate needs a documented way past it, because a production incident will eventually require shipping a fix while a scanner is unhappy, and if you have not designed that path someone will build a worse one. The design question is not whether an override exists but what it costs.
A workable override records who authorised it, why, and against which finding, posts that to a channel security reads, and expires. Expiry does the work. An override valid for seven days forces a real decision next week, whereas a permanent suppression added during an incident becomes an artefact nobody can explain a year later.
The metric to watch is the override rate per gate, not the total. One gate accounting for most of your overrides is telling you the rule is miscalibrated, and the correct response is to fix the rule rather than to remind people to stop using the override. Treat that number as feedback about your policy rather than about the teams.
How do you introduce a gate without a fight?
Run the rule in reporting mode first and publish what it would have done. Two to four weeks of data on your own codebase gives you a defensible answer to the only question that matters in the meeting: how many legitimate releases would this have stopped last month. Without that number the conversation is a contest of assertions, and the security side usually loses it.
Then enable the gate for new services and repositories before existing ones. Nobody objects to a rule that was there when they arrived, and it gives you a clean cohort to compare. Retrofitting to older services becomes scheduled work with an owner rather than an announcement.
Design the failure message, not just the policy. A gate that fails with the offending file, the rule, the fixed version if one exists and a link to the exception process costs the developer minutes. One that fails with a tool name and an exit code costs them an afternoon and buys you an enemy.
What should you check this week?
Pull the last thirty pipeline failures caused by a security check and sort them into three piles: real defects fixed, findings overridden, and findings that were not actionable by whoever was interrupted. If the third pile is the largest, your gates are calibrated wrong and the fix is a policy change rather than more training.
Then check whether any override in force today has an expiry date. If exceptions are permanent by default, you do not have a gate with an escape hatch, you have a gate with a growing hole. Adding expiry is usually a small configuration change and the highest-value adjustment available to most programmes.
Last, try to deploy an unsigned artefact to a non-production environment. If it succeeds, that is the gate to build next, because it decides whether anything else you check has consequences.
Common questions
- Should a build fail on critical vulnerabilities?
- Only when a fixed version exists and the developer being interrupted can apply it. Many critical findings sit in transitive dependencies with no patched release, so a gate on severity alone stops legitimate work with no available remedy. The predictable outcome is a bypass that becomes the normal route, leaving you with evidence of a check that no longer happens. Report those findings and track them to a deadline instead.
- What security checks should block a deployment?
- Detected secrets or private keys, infrastructure definitions that break an objective rule such as public storage or an administrative port open to the internet, containers set to run as root without a recorded exception, dependency findings above your threshold that have an available fix, and any artefact whose signature is missing or invalid at deploy. Each names a specific change and needs no judgement about exploitability.
- How do you add a security gate to a legacy codebase?
- Baseline the existing findings and gate only on what the current change introduces, using the tool's baseline, ratchet or new-code-only mode. Store the baseline in the repository so changes to it are reviewable, and give it a direction: the count may go down in any change and may not go up. For container images, gate on what the build adds relative to the base and handle inherited findings with a scheduled rebuild.
- Should there be a way to override a security gate?
- Yes, and it should be documented before you need it, because a production incident will eventually require shipping while a scanner is unhappy. A usable override records who authorised it, why, and against which finding, announces itself in a channel security reads, and expires after a short period so the decision gets revisited. Without an official path, teams build an unofficial one that leaves no record.
- How do you know a build gate is badly calibrated?
- Look at the override rate per rule rather than in total. If one gate accounts for most overrides, that rule is wrong for your environment and the fix is to change the rule. Also sort recent security-caused pipeline failures into real defects fixed, overrides, and findings the interrupted developer could not act on. A large third pile means the policy needs adjusting, not the teams.
- How should a failing security check present itself to a developer?
- With the offending file and line, the specific rule that fired, the fixed version if one exists, and a link to the exception process. That turns a failure into a few minutes of work. A failure that reports only a tool name and an exit code costs the developer an afternoon of investigation and steadily builds the case for switching the check off.