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.

You should either :

  • use a fixed version tag : using the maven:3.9.1 instead of maven:latest make sure you stay on a specific version of tools
    • prefer official image with the least tools (prefer minimal size, Alpine distribution or even distro-less if you can find one suited to your needs), the more the image has, heavier is the risk
  • build and maintain your own image with a chosen version for each tools
    • use no or a minimal distribution
    • upgrade tools and important components regularly with safe updates
    • root-less image are best 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 11 Medium, 1 Low, 2 Unknown
AnsibleANSIBLE_LINT_IMAGEdocker.io/haxorof/ansible-lint:latest
Amazon Web ServicesAWS_CLI_IMAGEdocker.io/amazon/aws-cli:latest
AzureAZURE_CLI_IMAGEmcr.microsoft.com/azure-cli:latest 3 Medium
BashBASH_BATS_IMAGEdocker.io/bats/bats:latest
BashBASH_SHELLCHECK_IMAGEdocker.io/koalaman/shellcheck-alpine:stable 2 High, 20 Medium, 4 Low, 2 Unknown
BrunoBRU_IMAGEdocker.io/library/node:lts-alpine 1 Low
GitLab ButlerBUTLER_IMAGEregistry.gitlab.com/to-be-continuous/tools/gitlab-butler:latest
Cloud FoundryCF_CLI_IMAGEdocker.io/governmentpaas/cf-cli 7 Critical, 24 High, 70 Medium, 3 Low, 1 Unknown
Cloud Native BuildpacksCNB_BUILDER_IMAGEdocker.io/paketobuildpacks/builder-jammy-base:latest 66 Critical, 97 High, 1303 Medium, 177 Low
Cloud Native BuildpacksCNB_SKOPEO_IMAGEquay.io/containers/skopeo:latest
Cloud Native BuildpacksCNB_TRIVY_IMAGEdocker.io/aquasec/trivy:latest 1 High, 3 Medium
CypressCYPRESS_IMAGEdocker.io/cypress/included:13.13.3 16 Critical, 146 High, 315 Medium, 306 Low, 24 Unknown
dbtDBT_IMAGEghcr.io/dbt-labs/dbt-core:latest 4 Critical, 244 High, 914 Medium, 601 Low, 3 Unknown
Docker ComposeDCMP_IMAGEdocker.io/library/docker:latest 4 Medium
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 2 Medium
DockerDOCKER_BUILDAH_IMAGEquay.io/containers/buildah:latest
DockerDOCKER_DIND_IMAGEdocker.io/library/docker:dind 4 Medium
DockerDOCKER_HADOLINT_IMAGEdocker.io/hadolint/hadolint:latest-alpine 8 High, 12 Medium
DockerDOCKER_IMAGEdocker.io/library/docker:latest 4 Medium
DockerDOCKER_KANIKO_IMAGEgcr.io/kaniko-project/executor:debug 5 High, 10 Medium
DockerDOCKER_SBOM_IMAGEdocker.io/anchore/syft:debug 1 Medium
DockerDOCKER_SKOPEO_IMAGEquay.io/containers/skopeo:latest
DockerDOCKER_TRIVY_IMAGEdocker.io/aquasec/trivy:latest 1 High, 3 Medium
.NETDOTNET_IMAGEmcr.microsoft.com/dotnet/sdk:latest 1 Critical, 20 High, 22 Medium, 97 Low
Google CloudGCP_CLI_IMAGEgcr.io/google.com/cloudsdktool/cloud-sdk:latest 5 Critical, 153 High, 458 Medium, 526 Low, 3 Unknown
GitleaksGITLEAKS_IMAGEdocker.io/zricethezav/gitleaks:latest 1 High
GitOpsGITOPS_IMAGEdocker.io/alpine/git:latest
GitLab PackageGLPKG_IMAGEdocker.io/curlimages/curl:latest
GoGO_CI_LINT_IMAGEdocker.io/golangci/golangci-lint:latest-alpine
GoGO_IMAGEdocker.io/library/golang:bookworm 1 Critical, 134 High, 429 Medium, 406 Low, 3 Unknown
GoGO_SBOM_IMAGE$GO_IMAGE not fetched
GoGO_SEMGREP_IMAGEdocker.io/semgrep/semgrep:latest 1 High, 1 Medium
GradleGRADLE_IMAGEdocker.io/library/gradle:latest 50 Medium, 34 Low
HelmfileHELMFILE_CLI_IMAGEghcr.io/helmfile/helmfile:latest 2 Critical, 7 High, 43 Medium, 1 Low
HelmHELM_CLI_IMAGEdocker.io/alpine/helm:latest
HelmHELM_KUBE_SCORE_IMAGEdocker.io/zegl/kube-score 8 Critical, 52 High, 77 Medium, 2 Low
HelmHELM_YAMLLINT_IMAGEdocker.io/cytopia/yamllint 7 High, 12 Medium, 2 Unknown
HurlHURL_IMAGEghcr.io/orange-opensource/hurl:latest
k6K6_IMAGEdocker.io/grafana/k6:latest
KubernetesK8S_KUBECTL_IMAGEdocker.io/bitnami/kubectl:latest 3 Critical, 24 High, 24 Medium, 100 Low
KubernetesK8S_KUBE_SCORE_IMAGEdocker.io/zegl/kube-score:latest 8 Critical, 52 High, 77 Medium, 2 Low
LighthouseLHCI_IMAGEdocker.io/cypress/browsers:latest 5 Critical, 44 High, 189 Medium, 248 Low, 24 Unknown
GNU MakeMAKE_IMAGEdocker.io/alpinelinux/build-base 6 High, 14 Medium, 6 Low, 3 Unknown
MavenMAVEN_IMAGEdocker.io/library/maven:latest 17 Medium, 29 Low
MkDocsMKD_IMAGEdocker.io/squidfunk/mkdocs-material:latest 2 High, 3 Medium
MkDocsMKD_LYCHEE_IMAGEdocker.io/lycheeverse/lychee:latest 1 Critical, 7 High, 12 Medium, 60 Low
MobSFMOBSF_CLIENT_IMAGEdocker.io/badouralix/curl-jq
AngularNG_CLI_IMAGEdocker.io/trion/ng-cli-karma:latest 3 Critical, 141 High, 444 Medium, 501 Low, 3 Unknown
Node.jsNODE_IMAGEdocker.io/library/node:lts-alpine 1 Low
Node.jsNODE_SEMGREP_IMAGEdocker.io/semgrep/semgrep:latest 1 High, 1 Medium
OSS Review Toolkit (ORT)ORT_SCANNER_IMAGEghcr.io/oss-review-toolkit/ort:latest 12 Critical, 83 High, 1131 Medium, 190 Low
OpenShiftOS_CLI_IMAGEquay.io/openshift/origin-cli:latest 1 High, 6 Medium
PHPPHP_IMAGEdocker.io/library/php:latest 3 Critical, 135 High, 417 Medium, 372 Low, 3 Unknown
PlaywrightPLAYWRIGHT_IMAGEmcr.microsoft.com/playwright:latest 3 High, 635 Medium, 146 Low
PostmanPOSTMAN_IMAGEdocker.io/postman/newman:latest 6 High, 30 Medium, 8 Low, 2 Unknown
pre-commitPRE_COMMIT_IMAGEdocker.io/library/python:3-alpine
PuppeteerPUPPETEER_IMAGEghcr.io/puppeteer/puppeteer:latest 9 Critical, 161 High, 503 Medium, 692 Low, 5 Unknown
PythonPYTHON_IMAGEdocker.io/library/python:3-slim 1 Critical, 7 High, 14 Medium, 62 Low
RenovateRENOVATE_IMAGEdocker.io/renovate/renovate:latest 690 Medium, 67 Low
Robot FrameworkROBOT_BASE_IMAGEdocker.io/ppodgorsek/robot-framework:latest 1 Critical, 3 High, 3 Medium
Source-to-ImageS2I_DIND_IMAGEdocker.io/library/docker:dind 4 Medium
Source-to-ImageS2I_SKOPEO_IMAGEquay.io/containers/skopeo:latest
S3 (Simple Storage Service)S3_CMD_IMAGEdocker.io/d3fk/s3cmd:latest
Scala/SBTSBT_IMAGEdocker.io/sbtscala/scala-sbt:17.0.2_1.6.2_3.1.3 55 Critical, 222 High, 298 Medium, 620 Low, 9 Unknown
Scala/SBTSBT_SBOM_IMAGEdocker.io/anchore/syft:debug 1 Medium
semantic-releaseSEMREL_IMAGEdocker.io/library/node:lts-slim 1 Critical, 7 High, 12 Medium, 59 Low
SonarQubeSONAR_SCANNER_IMAGEdocker.io/sonarsource/sonar-scanner-cli:latest 58 High, 36 Medium, 2 Low
SpectralSPECTRAL_IMAGEdocker.io/stoplight/spectral:latest 6 High, 29 Medium, 8 Low, 2 Unknown
SphinxSPHINX_IMAGEghcr.io/sphinx-doc/sphinx:latest 5 Critical, 24 High, 43 Medium, 170 Low
SphinxSPHINX_LYCHEE_IMAGEdocker.io/lycheeverse/lychee:latest 1 Critical, 7 High, 12 Medium, 60 Low
SQLFluff lintSQLFLUFF_IMAGEdocker.io/sqlfluff/sqlfluff:latest 2 Critical, 7 High, 20 Medium, 85 Low
Test SSLTESTSSL_IMAGEdocker.io/drwetter/testssl.sh:latest
TerraformTF_CHECKOV_IMAGEdocker.io/bridgecrew/checkov 1 Critical, 16 High, 30 Medium, 103 Low
TerraformTF_DOCS_IMAGEquay.io/terraform-docs/terraform-docs:edge 1 High, 2 Medium
TerraformTF_IMAGEdocker.io/hashicorp/terraform:latest 1 High, 2 Medium, 1 Low
TerraformTF_INFRACOST_IMAGEdocker.io/infracost/infracost 72 Critical, 734 High, 591 Medium, 21 Low, 2 Unknown
TerraformTF_PUBLISH_IMAGEdocker.io/curlimages/curl:latest
TerraformTF_TFLINT_IMAGEghcr.io/terraform-linters/tflint-bundle:latest 7 Critical, 35 High, 136 Medium, 5 Low, 2 Unknown
TerraformTF_TFSEC_IMAGEdocker.io/aquasec/tfsec-ci 2 High, 3 Medium, 1 Low
TerraformTF_TRIVY_IMAGEdocker.io/aquasec/trivy 1 High, 3 Medium