Policies and gates by application level
Not all applications require the same level of security, but all must comply with clear policies, proportional to their risk. This practice defines the automated application of policies, gates and controls by application level, ensuring that:
- Criticality dictates the rigour of the control mechanisms;
- Bypass is only possible upon formal and auditable justification.
The absence of a clear policy inevitably leads to inconsistent and permissive pipelines.
🎯 Objectives
- Prevent critical applications from advancing in the pipeline without mandatory validations;
- Ensure that security policies are applied consistently, automatically and auditably;
- Prevent informal bypass of critical stages in CI/CD.
🛠️ Practices
-
Explicit classification of the application (L1–L3)
- The risk level of the application must be defined (e.g. in a
.risk-level.ymlfile, an environment variable, a repository tag); - That classification must determine the behaviour of the pipeline.
- The risk level of the application must be defined (e.g. in a
-
Conditional application of policies and controls
- L3 applications require signed provenance, formal review of findings, minimum coverage, etc.;
- Policies must be coded directly into the pipeline (e.g. YAML templates, conditional workflows, policy-as-code).
-
Automated, blocking security gates
- Automated checks must prevent the pipeline from advancing if controls are not met;
- They must be mandatory for levels L2 and L3 (e.g. SAST, coverage, SBOM, analysis of findings).
-
Formal management of exceptions and bypass
- Exceptions must be recorded, justified and formally approved (e.g. via
change request); - Advancing with critical applications without explicit security validation is not permitted.
- Exceptions must be recorded, justified and formally approved (e.g. via
-
Periodic review and update of policies
- Policies must be maintained in versioned and auditable templates;
- There must be a mechanism to verify the version of the policy applied (e.g.
policy-version.yml).
⚖️ Proportional application by risk level
| Level | Policy requirements | Blocking criteria |
|---|---|---|
| L1 | Basic rules (e.g. clean build, light SAST) | Build fails on a critical error |
| L2 | Validated findings; minimum coverage; secrets checked | High-severity findings prevent promotion |
| L3 | Complete gates: SAST, DAST, IaC, SBOM, provenance | Advances only with formal security approval |
📌 Practical examples
-
GitHub Actions
- Conditional workflows with
.risk-level.yml; required status checksfor specific gates (SAST passed, coverage OK).
- Conditional workflows with
-
GitLab CI
rules:with variables such asAPP_CRITICALITY=L3;when: manualstages with security approval for L3.
-
Azure DevOps
Environmentswithapproval gatesandbranch protection;- YAML + branch policies for conditional enforcement.
-
Jenkins
- Use of
when { expression { isCritical() } }to activate enhanced stages; - Integration with policy-as-code tools (e.g. Open Policy Agent - OPA).
- Use of
📉 Mitigated risks
- Deploys of critical applications without mandatory validation (OSC&R: CI0006, CI0014);
- Divergence between organisational policy and what the pipeline applies;
- Informal or accidental bypass of security stages (OSC&R: CI0002).