# Security Quality Gates and Release Blocking

![Security Quality Gates](/files/cKC3Y4d48vXbOwjRbUHK)

> **Intro:** A quality gate is not a scanner. It is a delivery decision backed by evidence. In a strong DevSecOps program, gates are attached to real release moments such as **merge, package, promote, and production deploy**, and they are designed to stop meaningful risk without turning security into a permanent bottleneck.
>
> **What this page includes**
>
> * how to design quality gates that fit fast delivery
> * how to treat security and compliance as code instead of paperwork
> * how to preserve separation of duties without rebuilding slow CAB-era flow
> * practical gate logic for GitLab-style pipelines

## What a gate actually is

A **security quality gate** is a policy decision made from one or more technical signals.

Typical inputs:

* SAST on changed code;
* dependency and image scan results;
* secret detection;
* IaC or configuration linting;
* DAST or contract conformance checks;
* approval state for sensitive environments;
* evidence that the artifact is signed, traceable, and built from the expected path.

Typical outputs:

* **pass** — continue automatically;
* **fail** — block merge, build, release, or deploy;
* **manual review required** — named approver or risk acceptance required.

## Design principles for gates that developers will actually keep

### 1. Gate small changes, often

Small, frequent changes are easier to review, test, roll back, and understand. Big-bang releases create the worst security and compliance dynamics because every defect becomes urgent and hard to isolate.

### 2. Prefer new-code hygiene over full historical cleanup

The healthiest long-term model is usually:

* strong rules for **newly introduced risk**;
* visible but separately managed **legacy debt**;
* exception handling that is explicit, time-bounded, and owned.

### 3. Treat compliance as code

Policies should be enforced in the same delivery system that ships the change. The most scalable audit story is not a meeting note. It is:

* versioned pipeline logic;
* versioned approval rules;
* machine-readable scan results;
* immutable build and deploy evidence;
* exceptions recorded with owner and expiry.

### 4. Preserve separation of duties with controls, not theater

DevOps changes classic separation of duties, but it does not eliminate control. The practical replacement is:

* branch protection and code review;
* protected environments;
* approval rules for sensitive deploys;
* auditable pipelines;
* restricted runner trust;
* detective controls for out-of-band changes.

## Recommended gate stack

| Gate                | Purpose                              | Time budget              | Common checks                                                       |
| ------------------- | ------------------------------------ | ------------------------ | ------------------------------------------------------------------- |
| **MR gate**         | stop bad new code early              | minutes                  | SAST, secrets, dependency delta, lint, unit tests                   |
| **package gate**    | stop unsafe artifacts from promotion | minutes                  | image scan, provenance, IaC checks, ownership of suppressions       |
| **release gate**    | verify deploy-readiness              | minutes to low tens      | DAST baseline, contract checks, signed artifact, approval status    |
| **production gate** | protect high-trust environment       | short manual + automated | protected environment approval, evidence review, rollback readiness |

## Merge-request gate example

Use this gate for **fast, precise checks** on changed code and configuration.

Recommended inputs:

* Semgrep or GitLab SAST against the MR branch;
* secret scanning;
* dependency delta scan;
* IaC lint on changed Terraform or YAML;
* SonarQube or equivalent quality signal on new code.

## Packaging gate example

Use this gate before image or artifact promotion.

Recommended inputs:

* image scan result;
* base image policy and freshness;
* SBOM generation;
* artifact digest capture;
* image signing or provenance record;
* restricted registry target.

## Release gate example

Use this before production deploy.

Recommended inputs:

* DAST baseline or endpoint health security checks;
* OpenAPI contract lint and authz-sensitive review where relevant;
* deployment approval for protected environments;
* evidence package for auditability.

## A practical GitLab-style gate pattern

```yaml
stages:
  - sast
  - sca
  - package
  - security_gate
  - deploy

security_gate:
  stage: security_gate
  image: alpine:3.20
  needs:
    - semgrep_sast
    - trivy_fs
    - trivy_image
    - secret_scan
  script:
    - apk add --no-cache jq bash
    - ./ci/scripts/security_gate.sh
  rules:
    - if: $CI_COMMIT_BRANCH
```

Example `security_gate.sh`:

```bash
#!/usr/bin/env bash
set -euo pipefail

# Example by Ivan Piskunov, 2026.
# Turn multiple scanner outputs into one delivery decision.

critical_semgrep=$(jq '[.results[]? | select(.extra.severity == "ERROR")] | length' semgrep.json)
critical_trivy=$(jq '[.Results[]?.Vulnerabilities[]? | select(.Severity == "CRITICAL")] | length' trivy-image.json)
secrets_found=$(jq '[.findings[]?] | length' secrets.json)

if [ "$secrets_found" -gt 0 ]; then
  echo "[FAIL] secrets detected in change set"
  exit 1
fi

if [ "$critical_semgrep" -gt 0 ]; then
  echo "[FAIL] critical SAST findings on new code"
  exit 1
fi

if [ "$critical_trivy" -gt 0 ]; then
  echo "[FAIL] critical image vulnerabilities exceed release policy"
  exit 1
fi

echo "[PASS] security gate satisfied"
```

## A practical CI/CD backlog model borrowed from the DevSecOps Playbook

One of the most useful public planning models here comes from the 6mile **DevSecOps Playbook**. It breaks the pipeline domain into a backlog that is easier to sequence than generic “shift left” language.

### Controls worth importing directly

| Imported control idea                      | Why it matters                                                             | Where it belongs in this KB                             |
| ------------------------------------------ | -------------------------------------------------------------------------- | ------------------------------------------------------- |
| separate dev / staging / prod environments | reduces control confusion and bad assumptions                              | protected environments, environment-specific jobs       |
| non-production data separation             | prevents accidental production-data reuse                                  | preview / test environment policy and masking strategy  |
| CI/CD administration controls              | prevents people from disabling the very checks meant to protect the system | runner trust, workflow admin boundaries, protected refs |
| secure credential store                    | avoids plaintext pipeline secrets and brittle manual injection             | vault / native secret stores / OIDC                     |
| centralized SCA / SAST / secrets detection | creates reliable evidence-producing gates                                  | merge, package, and release lanes                       |
| DAST in CI/CD                              | adds runtime or semi-runtime validation for the right apps                 | release or dedicated test lanes                         |
| transient compute freshness                | reduces pipeline exposure from stale runners and images                    | runner base images and ephemeral compute                |
| transient compute hardening                | treats the build system itself as a target                                 | hardened runners, restricted privileges, isolation      |

### Why this model is useful

It turns “security in the pipeline” into a practical order of work:

1. create the pipeline and environments;
2. protect administration and secrets;
3. add centralized scanners;
4. add DAST and higher-friction runtime checks selectively;
5. harden the transient compute that executes all of this.

That sequence is easier to fund and explain than dropping twenty tools into CI at once.

### What should usually be priority-1 in modern teams

* pipeline as code under review;
* protected branches and protected environments;
* secure secret handling or OIDC;
* centralized SCA and secret scanning;
* at least one baseline SAST lane.

### What usually comes after the basics

* deeper static analysis;
* DAST for externally reachable or auth-sensitive systems;
* strict admin separation for workflow and deploy policy changes;
* hardening and regular refresh of runner or ephemeral build images.

### A modern caution on DAST

The imported playbook is right to keep **DAST** in the backlog, but do not read that as “every pull request must run a giant crawler.” In current practice, DAST belongs where:

* the app surface is stable enough to scan meaningfully;
* authentication can be handled safely;
* signal can be triaged without drowning delivery.

### A modern caution on transient compute

The playbook’s transient-compute items are especially important now. The build runner, action runner, or ephemeral CI pod is part of your attack surface. Treat freshness and hardening as first-class controls, not platform housekeeping.

## Control design for auditors and release managers

A defensible audit posture in DevSecOps usually includes:

* all pipeline definitions in version control;
* protected branches and protected environments;
* named approvers for privileged releases;
* immutable build identifiers and artifact digests;
* evidence that changes passed the expected checks;
* logging of exceptions, suppressions, and emergency changes.

## Change control without CAB drag

Traditional CAB processes were built for large, infrequent changes. DevSecOps works best with many small changes under tighter automation. That means:

* make standard low-risk changes flow automatically;
* reserve manual review for high-impact or high-uncertainty changes;
* use canary, dark launch, or staged rollout to reduce blast radius;
* keep rollback and forward-fix paths ready.

## Good blocker vs bad blocker

### Good blocker

* prevents a secret from shipping;
* prevents a production deploy from an unsigned artifact;
* prevents a new privileged container in a restricted namespace;
* prevents a high-confidence authz regression from merging.

### Bad blocker

* fails on old low-priority debt unrelated to the change;
* blocks on noisy findings with no triage policy;
* duplicates another gate without adding decision value;
* forces manual reviews that add no new information.

## Practical exception model

Every exception should record:

* the exact rule bypassed;
* reason and business context;
* owner;
* compensating controls;
* expiry date;
* review trigger.

## Cross-links

* [Runner Isolation and Trust Boundaries](/devsecops-cicd-and-supply-chain/index-1/runner-isolation-and-trust-boundaries.md)
* [Protected Environments and Deployment Approvals](/devsecops-cicd-and-supply-chain/index-1/protected-environments-and-deployment-approvals.md)
* [GitLab Release Evidence](/devsecops-cicd-and-supply-chain/index-1/gitlab-release-evidence.md)
* [Repository Governance — CODEOWNERS, SECURITY.md, and Default Files](/devsecops-cicd-and-supply-chain/index-1/repository-governance-codeowners-security-md-and-default-files.md)
* [Policy Exception Governance Pack](/metrics-audit-risk-evidence-and-compliance/index/policy-exception-governance-pack.md)

***

*Author attribution: Ivan Piskunov, 2026 - Educational and defensive-engineering use.*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.product-security.expert/devsecops-cicd-and-supply-chain/index-1/security-quality-gates-and-release-blocking.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
