Secure pipeline design
The secure design of CI/CD pipelines is a fundamental control to ensure that only legitimate, authorised and traceable changes are processed automatically. The pipeline must be treated as sensitive infrastructure, with the same security precautions that apply to source code, infrastructure scripts or privileged configurations.
The integrity of continuous delivery depends directly on the integrity of the pipelines themselves.
🎯 Objectives
- Ensure that only authorised changes trigger executions;
- Ensure that the execution flow is controlled and predictable;
- Protect against malicious manipulation of the pipeline (e.g. substitution of scripts, bypassing of stages);
- Enable traceability and independent review of everything the pipeline does.
🛠️ Practices
-
Pipelines as code (PaC)
- Pipelines must be defined as versioned files (e.g. YAML, JSON, HCL), in controlled repositories;
- All changes must be traceable and subject to formal review via pull/merge request.
-
Controlled and explicit triggers
- Only triggers from authorised sources must be accepted (e.g. merge to the main branch, push to a monitored branch, signed tag);
- Executions on forks or external branches must be disabled or mediated.
-
Mandatory review of changes to the pipeline
- Changes to pipeline files (e.g.
.github/workflows/*.yml) must require technical and/or security review; - A "four-eyes" policy must apply (at least two reviewers).
- Changes to pipeline files (e.g.
-
Separation of pipelines by function or criticality
- CI and CD must be distinct pipelines, with differentiated controls and permissions;
- Applications classified as L3 must have dedicated pipelines, segregated from generic pipelines.
-
Reusable, centralised templates
- The use of templates enables centralised validation and reduces the risk of error or manipulation;
- Templates must be versioned, auditable and reviewed periodically.
⚖️ Proportional application by risk level
| Level | Mandatory requirements | Enhanced requirements |
|---|---|---|
| L1 | Versioned pipelines; controlled triggers | - |
| L2 | Mandatory review; separate CI/CD | Reusable templates; automated validation |
| L3 | Security review; isolated pipelines | Formal approval of changes to the pipeline |
📌 Practical examples
-
GitHub Actions
required reviewersfor.github/workflows;- Disable automatic executions on forks (
pull_request_target).
-
GitLab CI
- Use of
rules:andonly:to control triggers; - Mandatory approval rules for
.gitlab-ci.yml.
- Use of
-
Azure DevOps
- Branch protection policy and PR gates for
azure-pipelines.yml; - YAML templates in a separate repository with controlled access.
- Branch protection policy and PR gates for
-
Jenkins
- Declarative pipelines versioned in Git;
- Protection of scripts with the Script Approval Plugin.
📉 Mitigated risks
- Unauthorised executions (OSC&R: CI0001, CI0004);
- Malicious substitution of scripts (OSC&R: CI0011);
- Manipulation of the build flow (OSC&R: CI0002);
- Abuse of automatic triggers (OSC&R: CI0006, CI0015).