DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • What Is API-First?
  • The DevSecOps Paradox: Why Security Automation Is Both Solving and Creating Pipeline Vulnerabilities
  • Securing Secrets: A Guide To Implementing Secrets Management in DevSecOps Pipelines
  • What Do You Need To Know About DevOps Lifecycle Phases?

Trending

  • 11 Agentic Testing Tools to Know in 2026
  • AI Agents in Java: Architecting Intelligent Health Data Systems
  • Bringing Intelligence Closer to the Source: Why Real-Time Processing is the Heart of Edge AI
  • RAG Is Not Enough: Advanced Retrieval Architectures Using Vertex AI Search on GCP
  1. DZone
  2. Software Design and Architecture
  3. Security
  4. DevSecOps: Enhancing Security With Vulnerability Scanning of Images and Source Code in CI/CD

DevSecOps: Enhancing Security With Vulnerability Scanning of Images and Source Code in CI/CD

This guide shows how to use Syft, Grype, and Trivy to scan container images for vulnerabilities in Gitlab pipelines during release.

By 
Vasilii Kulazhenkov user avatar
Vasilii Kulazhenkov
·
Aug. 03, 23 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
4.4K Views

Join the DZone community and get the full member experience.

Join For Free

Many companies strive to adopt the DevOps approach for software development and delivery. Alongside this, they face increasing security challenges, leading to the implementation of new innovative software development methods.

The need for security in the software deployment process is evident. Therefore, integrating security into CI/CD workflows should be done carefully to account for the ever-evolving technological landscape.

DevSecOps is an important concept that provides an automated approach to integrating security into the software delivery lifecycle. In the context of container solutions, there are specific challenges in adding security controls.

Furthermore, when using open-source containers, many of them may contain known and unknown vulnerabilities. For many organizations, it is difficult to determine the security of their containers confidently. Hence, these tools provide additional capabilities and features that facilitate faster implementation. However, not all of them always align with the organization's security goals. The reality is that lacking the skill to design secure deployment pipelines can come at a high cost to a company.

This article presents a guide on setting up, running, and using Syft, Grype, and Trivy in CI/CD. It describes how to automatically configure the release process to scan container images for vulnerabilities with Gitlab pipelines.

Solution Overview

Syft, Grype, and Trivy are popular vulnerability scanning tools used in the software development and deployment process. Here's a brief overview of each tool:

  • Syft: Developed by Anchore, Syft is an open-source command-line tool that focuses on scanning container images for vulnerabilities. It provides a detailed analysis of the container's software bill of materials (SBOM) by inspecting package managers, libraries, and dependencies. Syft also has integrations with various container registries and orchestration platforms to simplify the scanning process.
  • Grype: Also developed by Anchore, Grype is another open-source vulnerability scanner specifically designed for container images. It scans the image's software composition analysis (SCA) data to identify any known vulnerabilities. Grype's strength lies in its fast scanning capability and ability to handle complex image layers and formats.
  • Trivy: Trivy is an open-source vulnerability scanner that specializes in container images, as well as operating systems and applications. It uses vulnerability databases from various sources, including NVD, Red Hat, and Ubuntu, to detect known vulnerabilities in container images. Trivy is easy to use, offers extensive configuration options, and provides rapid and reliable scanning results.

Get Started

For scanning, you can use an Alpine Linux image; let's assume the latest version. We embed an additional step before loading the collected image into the registry, saving dependency lists in the artifacts of the task, and storing the database in the cache.

Here is a complete set of scans and reports received:

GitHub Flavored Markdown
 
variables:
  GO_VERSION: '1.20'

stages:
  - build
  - scan
  - upload

build:
  stage: build
  tags:
    - docker
    - dind
  image: golang:1.20-bullseye
  variables:
    DOCKER_DRIVER: overlay2
    DOCKER_HOST: tcp://docker:2376
    DOCKER_TLS_VERIFY: 1
    DOCKER_TLS_CERTDIR: "/certs"
    DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
  before_script:
    - |
      TIME=30; PASS=0
      echo "Waiting for docker daemon..."
      until [ -f "${DOCKER_CERT_PATH}/ca.pem" ] || [ ${TIME} -lt ${PASS} ]
      do
        echo -n ".";PASS=`expr $PASS + 1`; sleep 1
      done
  script:
    - make gobuild
  artifacts:
    name: "$CONTAINER_NAME"
    expire_in: 1h
    paths:
      - build/

upload:
  stage: upload
  needs:
    - scan
  dependencies: ["build"]
  tags:
    - docker
    - dind
  image: docker:23.0.3
  variables:
    DOCKER_DRIVER: overlay2
    DOCKER_HOST: tcp://docker:2376
    DOCKER_TLS_VERIFY: 1
    DOCKER_TLS_CERTDIR: "/certs"
    DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
  before_script:
    - |
      TIME=30; PASS=0
      echo "Waiting for docker daemon..."
      until [ -f "${DOCKER_CERT_PATH}/ca.pem" ] || [ ${TIME} -lt ${PASS} ]
      do
        echo -n ".";PASS=`expr $PASS + 1`; sleep 1
      done
  script:
    - |
      echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER $CI_REGISTRY --password-stdin
      docker build -t $CI_COMMIT_REF_SLUG:$CI_COMMIT_REF_SLUG .
      docker push $CI_COMMIT_REF_SLUG:$CI_COMMIT_REF_SLUG
      docker save $CI_COMMIT_REF_SLUG:$CI_COMMIT_REF_SLUG -o build/$CI_PROJECT_NAME.tar
  artifacts:
    name: "$CONTAINER_NAME"
    expire_in: 1h
    paths:
      - build/

scan_cve:
  stage: scan
  image: alpine:latest
  dependencies: ["build"]
  variables:
    GIT_STRATEGY: clone
    SYFT_REGISTRY_AUTH_AUTHORITY: "$CI_REGISTRY"
    SYFT_REGISTRY_AUTH_USERNAME:  "$CI_REGISTRY_USER"
    SYFT_REGISTRY_AUTH_PASSWORD:  "$CI_REGISTRY_PASSWORD"
    SYFT_FILE_CONTENTS_SKIP_FILES_ABOVE_SIZE: 20000000
    GRYPE_REGISTRY_AUTH_AUTHORITY: "$CI_REGISTRY"
    GRYPE_REGISTRY_AUTH_USERNAME:  "$CI_REGISTRY_USER"
    GRYPE_REGISTRY_AUTH_PASSWORD:  "$CI_REGISTRY_PASSWORD"
    GRYPE_DB_CACHE_DIR: "./.cache/grype/"
    GRYPE_EXCLUDE: "./.cache"
    TRIVY_USERNAME: "$CI_REGISTRY_USER"
    TRIVY_PASSWORD: "$CI_REGISTRY_PASSWORD"
    TRIVY_AUTH_URL: "$CI_REGISTRY"
    TRIVY_NO_PROGRESS: "true"
    TRIVY_CACHE_DIR: "./.cache/trivy/"
    TRIVY_VERSION: "v0.43.1"
    FULL_IMAGE_NAME: "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
    IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
  allow_failure: true
  cache:
    key: $CI_JOB_NAME
    paths:
      - ./.cache/
  before_script:
    - apk add --update-cache curl openssl docker-cli
    - mkdir -p ./.out
    - export TRIVY_VERSION=${TRIVY_VERSION:-v0.43.1}
    - curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
    - curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
    - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin #${TRIVY_VERSION}
    - curl -sSL -o /tmp/trivy-gitlab.tpl https://github.com/aquasecurity/trivy/raw/main/contrib/gitlab.tpl
    - curl -sSL -o /tmp/trivy-codequality.tpl https://github.com/aquasecurity/trivy/raw/main/contrib/gitlab-codequality.tpl
    - curl -sSL -o /tmp/trivy-html.tpl https://github.com/aquasecurity/trivy/raw/main/contrib/html.tpl
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - echo "--- SYFT ---"
    - time syft packages registry:$FULL_IMAGE_NAME --scope all-layers
    - time syft packages dir:./ --scope all-layers -o table=.out/syft_sbom.txt -o spdx-json=.out/syft_sbom_spdx.json
    - echo "--- GRYPE ---"
    - time grype db update
    - time grype dir:./ --add-cpes-if-none -o table > .out/grype_cve_table.txt
    - time grype dir:./ --add-cpes-if-none -o json > .out/grype_cve_json.json
    - time grype dir:./ --add-cpes-if-none -o cyclonedx > .out/grype_cyclonedx.xml  ## this one is ok
    - time grype sbom:.out/syft_sbom_spdx.json --add-cpes-if-none --fail-on critical --only-fixed
    - time grype dir:./ --add-cpes-if-none
    - time grype dir:./ --add-cpes-if-none --only-fixed
    - time grype build/$CONTAINER_NAME --add-cpes-if-none -o table #--fail-on critical --only-fixed
    - time grype registry:$FULL_IMAGE_NAME --add-cpes-if-none --fail-on critical --only-fixed
    - echo "--- TRIVY ---"
    - trivy --version
    - time trivy image --clear-cache
    - time trivy image --download-db-only
    - time trivy image --exit-code 0 --format template --template "@/tmp/trivy-gitlab.tpl" -o .out/trivy_cve.json $IMAGE
    - time trivy image --exit-code 0 --format template --template "@/tmp/trivy-codequality.tpl" -o .out/trivy_codequality.json $IMAGE
    - time trivy image --exit-code 0 --format template --template "@/tmp/trivy-gitlab.tpl" -o .out/gl-container-scanning-report.json $IMAGE
    - time trivy image --exit-code 0 --format template --template "@/tmp/trivy-html.tpl" -o .out/trivy_cve.html $IMAGE
    - time trivy sbom --format spdx -o ".out/trivy_sbom_fs_spdx.spdx" --type fs .
    - time trivy sbom --format spdx-json -o ".out/trivy_sbom_spdxjson.json" --type image "$FULL_IMAGE_NAME"
    - time trivy image --format cyclonedx -o ".out/trivy_sbom_cyclonedx.json" "$FULL_IMAGE_NAME"
    - time trivy image --exit-code 0 "$FULL_IMAGE_NAME"
    - time trivy image --exit-code 0 --severity CRITICAL "$FULL_IMAGE_NAME"
    - time trivy image --exit-code 1 --severity CRITICAL --ignore-unfixed "$FULL_IMAGE_NAME"
  artifacts:
    reports:
      dependency_scanning: .out/grype_cve.json
      container_scanning: .out/gl-container-scanning-report.json
      codequality: .out/trivy_codequality.json
    name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}
    paths:
      - .out/


The result of Grype 's in syft_sbom_spdx.json work looks something like this:

JSON
 
#grype sbom:.out/syft_sbom_spdx.json --add-cpes-if-none --fail-on critical --only-fixed
NAME                         INSTALLED  FIXED-IN  TYPE       VULNERABILITY        SEVERITY
go.mongodb.org/mongo-driver  v1.1.2     1.5.1     go-module  GHSA-f6mq-5m25-4r72  Medium


The result of Trivy in trivy_codequality.json work looks something like this:

JSON
 
#trivy image --exit-code 0 "$FULL_IMAGE_NAME"
2022-06-07T13:18:57.228Z  INFO  Detected OS: alpine
2022-06-07T13:18:57.229Z  INFO  Detecting Alpine vulnerabilities...
2022-06-07T13:18:57.230Z  INFO  Number of language-specific files: 1
2022-06-07T13:18:57.230Z  INFO  Detecting gobinary vulnerabilities...
Total: 2 (UNKNOWN: 1, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0)
┌─────────────────────────────┬────────────────┬──────────┬───────────────────┬───────────────┬──────────────────────────────────────────────────────────────┐
│           Library           │ Vulnerability  │ Severity │ Installed Version │ Fixed Version │                            Title                             │
├─────────────────────────────┼────────────────┼──────────┼───────────────────┼───────────────┼──────────────────────────────────────────────────────────────┤
│ go.mongodb.org/mongo-driver │ CVE-2021-20329 │ MEDIUM   │ v1.1.2            │ 1.5.1         │ mongo-go-driver: specific cstrings input may not be properly │
│                             │                │          │                   │               │ validated                                                    │
│                             │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2021-20329                   │
├─────────────────────────────┼────────────────┼──────────┼───────────────────┼───────────────┼──────────────────────────────────────────────────────────────┤
│ golang.org/x/text           │ CVE-2021-38561 │ UNKNOWN  │ v0.3.3            │ 0.3.7         │ Due to improper index calculation, an incorrectly formatted  │
│                             │                │          │                   │               │ language tag can cause...                                    │
│                             │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2021-38561                   │
└─────────────────────────────┴────────────────┴──────────┴───────────────────┴───────────────┴──────────────────────────────────────────────────────────────┘


Conclusion

Vulnerability scanning plays a crucial role in strengthening the security of software applications and ensuring a proactive approach to addressing vulnerabilities. By integrating vulnerability scanners into your CI pipeline for container images and source code, you can detect vulnerabilities early, maintain compliance, and foster a secure coding culture. Leveraging automation and comprehensive scanning tools allow teams to efficiently monitor and continuously improve the security of their software, ultimately delivering safer applications to end-users.

Contextual design JSON Software development Vulnerability Cache (computing) security

Opinions expressed by DZone contributors are their own.

Related

  • What Is API-First?
  • The DevSecOps Paradox: Why Security Automation Is Both Solving and Creating Pipeline Vulnerabilities
  • Securing Secrets: A Guide To Implementing Secrets Management in DevSecOps Pipelines
  • What Do You Need To Know About DevOps Lifecycle Phases?

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook