Skip to content

Security

Risks

CI/CD is the automation of most (if not all) process in your software lifecycle going from building to running the application in production. With so many things happening, attackers have a wide range of capabilities in case of a compromise:

  • introduce dubious components (i.e. backdoor) in the application,
  • leak (to the Internet) credentials granting access to internal services or infrastructures,
  • access said services or infrastructures,
  • impersonate an employee,
  • leak intellectual property,
  • ...

Every CI/CD job is executed inside a container image which contains various tools required by the job. When you are executing the job, you are trusting the people building the image and the tools.

In some cases, the image may have been corrupted by an attacker. This is what we call a supply chain attack. There are famous cases like the Codecov incident in which hackers managed to leak credentials from several services and cloud platforms.

Mitigations

Variables scoping

To prevent leakage, CI/CD variables has to be present only in jobs that need them. By example in the Maven template, only the mvn-sonar job actually needs the SONAR_TOKEN environment variable so others jobs (mvn-build, mvn-release...) should not access this secret.

You can find more info about how to protect your CI/CD variables in the official GitLab documentation.

Image selection

As much as we can, we try to select either official images (ex: Maven, Python), or at least images maintained by an active community. Each of those images can be freely overridden with the appropriate configuration variable to select fixed versions (more info here) or any alternative that would suit you more.

By default, to be continuous templates mostly use the latest tag from upstream images since it is a maintenance-less default that works for nearly everyone. However latest images are prone to supply chain attacks and are also likely to introduce breaking changes.

to be continuous is not responsible of any possible security issue from a default container image.

To mitigate the risks of using latest images, you should always use a fixed version tag (maven:3.9.1 instead of maven:latest) or build your own image.

Additional dependencies

However, the direct counterpart of using official images is that many default image do not ship all the required tools used by the template (think about git and curl utilities). For this reason, many templates check the presence of these additional dependencies and install them on the fly (see maybe_install_pkg function).

This is a good practice to avoid bloating the image with unnecessary tools, but it also means that you are trusting the upstream repositories of your distribution (i.e. Debian, Alpine, etc.) to not be compromised and requiring network access to download packages.

Every project is encouraged to maintain his own Docker image in order to fit to their needs, avoid extraneous downloading for additional dependencies and simplify the work of security team (it's easy to scan a Docker image). While doing so, we recommend to use a minimal distribution and root-less images to prevent some container escalation vulnerabilities against your runner provider.

Tip

Whenever building your own image or using an upstream image, you can use Renovate to watch updates for your tools, test the new version and integrate them seamlessly.

Vulnerability Reports (Trivy)

Important

When reviewing vulnerabilities from containers, you have to consider the following principes :

  • containers are usually very short-lived in a CI/CD environment
  • no direct user access is possible
  • most job does not expose any exteral services (i.e. HTTP server) making attacks reliant on user interaction very hard if not impossible to exploit

In short, risks are often low in the CI/CD context but carefully reviewing vulnerabilities are an essential step to secure your pipeline.

Here are vulnerability reports for each default image used by to be continuous templates (generated every day):

Template Image Variable Default Image Vulnerabilities
AnsibleANSIBLE_IMAGEdocker.io/cytopia/ansible:latest-tools 5 High, 21 Medium, 1 Low, 2 Unknown
AnsibleANSIBLE_LINT_IMAGEdocker.io/haxorof/ansible-lint:latest
Amazon Web ServicesAWS_CLI_IMAGEdocker.io/amazon/aws-cli:latest 1 High, 2 Medium, 2 Low
AzureAZURE_CLI_IMAGEmcr.microsoft.com/azure-cli:latest 2 High
BashBASH_BATS_IMAGEdocker.io/bats/bats:latest 3 Medium, 3 Low
BashBASH_SHELLCHECK_IMAGEdocker.io/koalaman/shellcheck-alpine:stable 7 Medium, 5 Low
BrunoBRU_IMAGEdocker.io/library/node:lts-alpine 2 High, 1 Medium
GitLab ButlerBUTLER_IMAGEregistry.gitlab.com/to-be-continuous/tools/gitlab-butler:latest 2 High, 4 Medium, 3 Low
Cloud FoundryCF_CLI_IMAGEdocker.io/governmentpaas/cf-cli 6 Critical, 40 High, 96 Medium, 3 Low, 2 Unknown
Cloud Native BuildpacksCNB_BUILDER_IMAGEdocker.io/paketobuildpacks/builder-jammy-base:latest 4 Critical, 307 High, 1916 Medium, 142 Low
Cloud Native BuildpacksCNB_SKOPEO_IMAGEquay.io/containers/skopeo:latest
Cloud Native BuildpacksCNB_TRIVY_IMAGEdocker.io/aquasec/trivy:latest 2 High, 8 Medium, 5 Low
CypressCYPRESS_IMAGEdocker.io/cypress/included:13.13.3 30 Critical, 187 High, 385 Medium, 326 Low, 31 Unknown
dbtDBT_IMAGEghcr.io/dbt-labs/dbt-core:latest 4 Critical, 395 High, 1503 Medium, 677 Low, 40 Unknown
Docker ComposeDCMP_IMAGEdocker.io/library/docker:latest 4 High, 8 Medium
Docker ComposeDCMP_KICS_IMAGEdocker.io/checkmarx/kics:latest 1 High, 1 Medium
DebianDEBIAN_BASE_IMAGEdocker.io/debian 10 Medium, 50 Low
DebianDEBIAN_BUILD_IMAGE$DEBIAN_BASE_IMAGE not fetched
DebianDEBIAN_LINT_IMAGE$DEBIAN_BASE_IMAGE not fetched
DefectDojoDEFECTDOJO_BASE_IMAGEdocker.io/library/node:alpine3.11 1 Critical, 25 High, 3 Medium, 2 Low
Dependency TrackDEPTRACK_SBOM_SCANNER_IMAGEregistry.gitlab.com/to-be-continuous/tools/dt-sbom-scanner:latest 1 Critical, 2 High, 11 Medium, 5 Low
DockerDOCKER_BUILDAH_IMAGEquay.io/containers/buildah:latest
DockerDOCKER_DIND_IMAGEdocker.io/library/docker:dind 4 High, 8 Medium
DockerDOCKER_HADOLINT_IMAGEdocker.io/hadolint/hadolint:latest-alpine 7 Medium, 5 Low
DockerDOCKER_IMAGEdocker.io/library/docker:latest 4 High, 8 Medium
DockerDOCKER_KANIKO_IMAGEgcr.io/kaniko-project/executor:debug 36 High, 65 Medium
DockerDOCKER_SBOM_IMAGEdocker.io/anchore/syft:debug 1 High, 3 Medium
DockerDOCKER_SKOPEO_IMAGEquay.io/containers/skopeo:latest
DockerDOCKER_TRIVY_IMAGEdocker.io/aquasec/trivy:latest 2 High, 8 Medium, 5 Low
.NETDOTNET_IMAGEmcr.microsoft.com/dotnet/sdk:10.0 8 Medium, 17 Low
.NETDOTNET_SBOM_IMAGEghcr.io/cyclonedx/cdxgen:master 24 High, 32 Medium, 1 Unknown
Google CloudGCP_CLI_IMAGEgcr.io/google.com/cloudsdktool/cloud-sdk:latest 4 Critical, 175 High, 628 Medium, 624 Low, 29 Unknown
GitleaksGITLEAKS_IMAGEdocker.io/zricethezav/gitleaks:latest 1 High, 14 Medium, 3 Low
GitOpsGITOPS_IMAGEdocker.io/alpine/git:latest 17 Medium, 3 Low
GitLab PackageGLPKG_IMAGEdocker.io/curlimages/curl:latest 3 Medium, 3 Low
GoGO_CI_LINT_IMAGEdocker.io/golangci/golangci-lint:latest-alpine 1 High, 1 Medium
GoGO_IMAGEdocker.io/library/golang:bookworm 2 Critical, 160 High, 589 Medium, 496 Low, 26 Unknown
GoGO_SBOM_IMAGE$GO_IMAGE not fetched
GoGO_SEMGREP_IMAGEdocker.io/semgrep/semgrep:latest 3 High, 2 Medium
GradleGRADLE_IMAGEdocker.io/library/gradle:latest 94 Medium, 32 Low
HelmfileHELMFILE_CLI_IMAGEghcr.io/helmfile/helmfile:latest 2 Critical, 42 High, 100 Medium, 4 Low
HelmHELM_CLI_IMAGEdocker.io/alpine/helm:latest 1 High, 6 Medium, 3 Low
HelmHELM_KUBE_SCORE_IMAGEdocker.io/zegl/kube-score 8 Critical, 70 High, 106 Medium, 3 Low
HelmHELM_YAMLLINT_IMAGEdocker.io/cytopia/yamllint 7 High, 13 Medium, 2 Unknown
HurlHURL_IMAGEghcr.io/orange-opensource/hurl:latest 3 Medium, 3 Low
k6K6_IMAGEdocker.io/grafana/k6:latest 1 High, 6 Medium, 3 Low
KubernetesK8S_KUBECTL_IMAGEdocker.io/alpine/k8s:MUST_SET_VERSION not fetched
KubernetesK8S_KUBE_SCORE_IMAGEdocker.io/zegl/kube-score:latest 8 Critical, 70 High, 106 Medium, 3 Low
LighthouseLHCI_IMAGEdocker.io/cypress/browsers:latest 9 High, 50 Medium, 198 Low, 3 Unknown
GNU MakeMAKE_IMAGEdocker.io/alpinelinux/build-base
MavenMAVEN_IMAGEdocker.io/library/maven:latest 80 Medium, 32 Low
MkDocsMKD_IMAGEdocker.io/squidfunk/mkdocs-material:latest 8 High, 7 Medium, 3 Low
MkDocsMKD_LYCHEE_IMAGEdocker.io/lycheeverse/lychee:latest 1 Critical, 4 High, 20 Medium, 60 Low, 1 Unknown
MobSFMOBSF_CLIENT_IMAGEdocker.io/badouralix/curl-jq 3 Medium, 3 Low
MobSFMOBSF_CODE_IMAGEdocker.io/opensecurity/mobsfscan:latest 6 Critical, 451 High, 1431 Medium, 500 Low, 25 Unknown
AngularNG_CLI_IMAGEdocker.io/trion/ng-cli-karma:latest 2 Critical, 175 High, 601 Medium, 612 Low, 26 Unknown
Node.jsNODE_IMAGEdocker.io/library/node:lts-alpine 2 High, 1 Medium
Node.jsNODE_SEMGREP_IMAGEdocker.io/semgrep/semgrep:latest 3 High, 2 Medium
OSS Review Toolkit (ORT)ORT_SCANNER_IMAGEghcr.io/oss-review-toolkit/ort:latest 13 Critical, 114 High, 1479 Medium, 167 Low, 1 Unknown
OpenShiftOS_CLI_IMAGEquay.io/openshift/origin-cli:latest 19 High, 71 Medium, 183 Low
PHPPHP_IMAGEdocker.io/library/php:latest 61 High, 141 Medium, 421 Low, 22 Unknown
PlaywrightPLAYWRIGHT_IMAGEmcr.microsoft.com/playwright:latest 6 High, 769 Medium, 149 Low
PostmanPOSTMAN_IMAGEdocker.io/postman/newman:latest 8 High, 31 Medium, 8 Low, 2 Unknown
pre-commitPRE_COMMIT_IMAGEdocker.io/library/python:3-alpine
PuppeteerPUPPETEER_IMAGEghcr.io/puppeteer/puppeteer:latest 7 Critical, 206 High, 639 Medium, 804 Low, 26 Unknown
PythonPYTHON_IMAGEdocker.io/library/python:3-slim 10 Medium, 51 Low
RenovateRENOVATE_IMAGEdocker.io/renovate/renovate:latest 3 High, 1116 Medium, 78 Low
Robot FrameworkROBOT_BASE_IMAGEdocker.io/ppodgorsek/robot-framework:latest 3 High
RPMRPM_BASE_IMAGEdocker.io/fedora
RPMRPM_BUILD_IMAGE$RPM_BASE_IMAGE not fetched
RPMRPM_LINT_IMAGE$RPM_BASE_IMAGE not fetched
RustRUST_IMAGEdocker.io/library/rust:latest 92 High, 201 Medium, 696 Low, 29 Unknown
Source-to-ImageS2I_DIND_IMAGEdocker.io/library/docker:dind 4 High, 8 Medium
Source-to-ImageS2I_SKOPEO_IMAGEquay.io/containers/skopeo:latest
Source-to-ImageS2I_TRIVY_IMAGEdocker.io/aquasec/trivy:latest 2 High, 8 Medium, 5 Low
S3 (Simple Storage Service)S3_CMD_IMAGEdocker.io/d3fk/s3cmd:latest 2 High, 5 Medium, 3 Low, 1 Unknown
Scala/SBTSBT_IMAGEdocker.io/sbtscala/scala-sbt:17.0.2_1.6.2_3.1.3 53 Critical, 238 High, 352 Medium, 695 Low, 14 Unknown
Scala/SBTSBT_SBOM_IMAGEdocker.io/anchore/syft:debug 1 High, 3 Medium
semantic-releaseSEMREL_IMAGEdocker.io/library/node:lts-slim 1 Critical, 6 High, 21 Medium, 58 Low, 1 Unknown
SonarQubeSONAR_SCANNER_IMAGEdocker.io/sonarsource/sonar-scanner-cli:latest 5 High, 2 Medium, 2 Low
SpectralSPECTRAL_IMAGEdocker.io/stoplight/spectral:latest 6 High, 29 Medium, 8 Low, 2 Unknown
SphinxSPHINX_IMAGEghcr.io/sphinx-doc/sphinx:latest 24 Critical, 62 High, 62 Medium, 183 Low, 2 Unknown
SphinxSPHINX_LYCHEE_IMAGEdocker.io/lycheeverse/lychee:latest 1 Critical, 4 High, 20 Medium, 60 Low, 1 Unknown
SQLFluff lintSQLFLUFF_IMAGEdocker.io/sqlfluff/sqlfluff:latest 3 Critical, 9 High, 34 Medium, 86 Low, 1 Unknown
Test SSLTESTSSL_IMAGEdocker.io/drwetter/testssl.sh:latest
TerraformTF_CHECKOV_IMAGEdocker.io/bridgecrew/checkov 9 High, 31 Medium, 87 Low, 1 Unknown
TerraformTF_DOCS_IMAGEquay.io/terraform-docs/terraform-docs:edge 6 High, 22 Medium, 6 Low
TerraformTF_IMAGEdocker.io/hashicorp/terraform:latest 1 High, 4 Medium, 3 Low
TerraformTF_INFRACOST_IMAGEdocker.io/infracost/infracost 72 Critical, 807 High, 727 Medium, 20 Low, 2 Unknown
TerraformTF_PUBLISH_IMAGEdocker.io/curlimages/curl:latest 3 Medium, 3 Low
TerraformTF_TFLINT_IMAGEghcr.io/terraform-linters/tflint-bundle:latest 7 Critical, 58 High, 173 Medium, 5 Low, 2 Unknown
TerraformTF_TFSEC_IMAGEdocker.io/aquasec/tfsec-ci 15 High, 34 Medium, 8 Low
TerraformTF_TRIVY_IMAGEdocker.io/aquasec/trivy 2 High, 8 Medium, 5 Low
ZolaZOLA_IMAGEdocker.io/jauderho/zola:latest
ZolaZOLA_LYCHEE_IMAGEdocker.io/lycheeverse/lychee:latest 1 Critical, 4 High, 20 Medium, 60 Low, 1 Unknown