GitLab CI/CD: Architecting, Deploying, and Optimizing Pipelines

Optimization Security and Monitoring

Template Container Scanning

Container Scanning is a critical part of Software Composition Analysis (SCA), inspecting Docker images and their base layers for known vulnerabilities. GitLab CI/CD offers a free Container Scanning template—powered by Trivy by default (or GRype)—to help you keep your images secure.

The image shows a GitLab documentation page about container scanning, detailing integration with open-source tools for vulnerability analysis. It includes navigation links on the left and an overview section in the main content area.

1. Enabling Container Scanning

Add the built-in Container Scanning template to your .gitlab-ci.yml:

include:
  - template: Jobs/Build.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml

container_scanning:
  variables:
    CS_DEFAULT_BRANCH_IMAGE: $CI_REGISTRY_IMAGE/$CI_DEFAULT_BRANCH:$CI_COMMIT_SHA

Note

By default, the container_scanning job runs in the test stage. Override CS_DEFAULT_BRANCH_IMAGE to scan a different image tag.

1.1 Scanning Remote Images

Override CS_IMAGE and log level:

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

variables:
  SECURE_LOG_LEVEL: debug

container_scanning:
  variables:
    CS_IMAGE: example.com/user/image:tag

1.2 Authenticating to a Private Registry

If your registry requires authentication, log in during before_script and supply credentials as CI variables:

container_scanning:
  before_script:
    - apk add --no-cache python3 py3-pip
    - pip3 install awscli
    - export AWS_ECR_PASSWORD=$(aws ecr get-login-password --region us-east-1)
    - docker login -u AWS -p "$AWS_ECR_PASSWORD" <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com
  include:
    - template: Security/Container-Scanning.gitlab-ci.yml
  variables:
    CS_IMAGE: <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/<image>:<tag>
    CS_REGISTRY_USER: AWS
    CS_REGISTRY_PASSWORD: "$AWS_ECR_PASSWORD"
    AWS_DEFAULT_REGION: us-east-1

2. Container Scanning CI/CD Variables

These variables control which image is scanned and how verbose the logs are:

VariableDefaultDescription
CS_DEFAULT_BRANCH_IMAGE$CI_REGISTRY_IMAGE/$CI_DEFAULT_BRANCH:$CI_COMMIT_SHAImage tag for default branch
CS_IMAGECustom image:tag to scan
CS_REGISTRY_USERUsername for private registry
CS_REGISTRY_PASSWORDPassword/token for registry login
SECURE_LOG_LEVELinfoLog verbosity (debug or info)
CS_ANALYZER_IMAGE$CI_TEMPLATE_REGISTRY_HOST/.../container-scanning:latestAnalyzer container used for scanning
CS_SCHEMA_MODELSchema version of the scanning output

The image shows a GitLab documentation page detailing available CI/CD variables for container scanning, including variable names, defaults, descriptions, and associated scanners.

The image shows a GitLab documentation page about container scanning, detailing CI/CD variables and their descriptions. The sidebar on the left lists various security and scanning options.

3. Allowlisting Vulnerabilities

To ignore specific CVEs, add a vulnerabilities-allowlist.yaml in your repo:

generalAllowlist:
  CVE-2019-8696:
  CVE-2014-8166: cups
  CVE-2017-18248:

images:
  registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:
    CVE-2018-4180:
  your.private.registry:5000/centos:
    CVE-2015-1419: libxml2
    CVE-2015-1447:

Warning

Allowlisting will mark these CVEs as approved and they will not fail your pipeline. Use with caution!

The image shows a GitLab documentation page about container scanning job log format, displaying a table of found vulnerabilities with details like status, CVE severity, package name, and version.

4. CycloneDX SBOM Output

Container Scanning also generates a CycloneDX SBOM artifact (gl-sbom-*.cdx.json), following the OWASP standard for Software Bill of Materials.

The image shows a GitLab documentation page about CycloneDX Software Bill of Materials and container scanning, including sections on the security dashboard and vulnerabilities database.

5. Integrating into a Full Pipeline

Below is an example .gitlab-ci.yml snippet that combines build, SAST, secret detection, and container scanning:

stages:
  - .pre
  - test
  - containerization
  - dev-deploy
  - stage-deploy

include:
  - component: gitlab.com/gitlab-components/code-quality/[email protected]
  - template: Jobs/SAST.gitlab-ci.yml
  - component: gitlab.com/gitlab-components/secret-detection/[email protected]
  - template: Security/Container-Scanning.gitlab-ci.yml

variables:
  DOCKER_USERNAME: siddharth67
  IMAGE_VERSION: "$CI_PIPELINE_ID"
  DOCKER_IMAGE: $DOCKER_USERNAME/solar-system:$IMAGE_VERSION
  CS_ANALYZER_IMAGE: "$CI_TEMPLATE_REGISTRY_HOST/security-products/container-scanning:6"
  CS_SCHEMA_MODEL: 15

container_scanning:
  stage: containerization
  needs:
    - docker_push
  image: "$CS_ANALYZER_IMAGE$CS_IMAGE_SUFFIX"
  variables:
    CS_IMAGE: docker.io/$DOCKER_USERNAME/solar-system:$IMAGE_VERSION
    GIT_STRATEGY: none
    allow_failure: true
  artifacts:
    reports:
      container_scanning: gl-container-scanning-report.json
      cyclonedx: "**/gl-sbom-*.cdx.json"

The image shows a GitLab Pipeline Editor interface with a visual representation of a CI/CD pipeline, including stages like "pre," "test," "containerization," "dev-deploy," and "stage-deploy," each containing various tasks. The left sidebar displays navigation options such as "Merge requests," "Manage," "Plan," and "Code."

6. Demo: Generating Vulnerabilities

To demonstrate detection, switch your Dockerfile from Alpine to Debian:

# Before: minimal Alpine image
FROM node:18-alpine3.11

# After: standard Debian-based Node.js
FROM node:18

WORKDIR /usr/app
COPY package*.json ./
RUN npm install
COPY . .
ENV MONGO_URI=uriPlaceholder
ENV MONGO_USERNAME=usernamePlaceholder
ENV MONGO_PASSWORD=passwordPlaceholder
EXPOSE 3000
CMD ["npm", "start"]

Commit to a feature branch to trigger the pipeline. You’ll see the Container Scanning job in the containerization stage.

The image shows a GitLab CI/CD pipeline interface for a NodeJS project, displaying various stages such as pre, test, containerization, and dev-deploy, with job statuses indicated by checkmarks and icons.

After completion, open the Container Scanning log to view the summary table or raw output.

The image shows a GitLab interface displaying a job log with details about a pipeline run, including a highlighted security warning related to a CVE vulnerability.

Additional deployment jobs will follow.

The image shows a GitLab CI/CD pipeline interface for a NodeJS project, displaying various stages and jobs such as code quality checks, testing, containerization, and deployment. Each job has a status indicator, with some marked as successful and others needing attention.

7. Inspecting the Reports

7.1 JSON Vulnerability Report

The gl-container-scanning-report.json artifact lists vulnerabilities in structured JSON:

{
  "vulnerabilities": [
    {
      "id": "de666e5aa0b170e90b8d7018c398ba76c577c",
      "severity": "Low",
      "location": {
        "dependency": {
          "package": {
            "name": "apt",
            "version": "2.6.1"
          },
          "image": "docker.io/siddharth67/solar-system:1165883818"
        }
      },
      "identifiers": [
        { "type": "cve", "name": "CVE-2011-3374" }
      ],
      "description": "apt-key in apt, all versions, do not correctly validate gpg keys, leading to a potential MITM attack."
    }
  ]
}

The image shows a GitLab documentation page about JSON report formats and CycloneDX Software Bill of Materials related to container scanning. It includes navigation links and text explaining the report formats and integration.

7.2 CycloneDX SBOM

The SBOM artifact follows the CycloneDX spec:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "component": {
    "type": "container",
    "name": "docker.io/siddharth67/solar-system",
    "version": "1.1.1"
  },
  "tools": [
    { "vendor": "aquasecurity", "name": "trivy", "version": "0.48.3" }
  ]
}

The image shows a GitLab documentation page about CycloneDX Software Bill of Materials, security dashboards, and vulnerabilities databases. It includes a sidebar with navigation options related to security and scanning features.


You now have a fully configured Container Scanning pipeline with vulnerability reports and SBOM output. Integrate additional scanners (Dependency, SAST, DAST) as needed based on your security requirements.

Watch Video

Watch video content

Previous
Component Secret Detection