Security has become a crucial part of every DevOps workflow. With applications running in containers, securing images before deploying them is more important than ever. Imagine deploying an application only to discover later that the container image had critical vulnerabilities. That single mistake can put the entire system at risk.
To address this, you can integrate Trivy, an open-source vulnerability scanner, with GitHub Actions. This setup scans every container image automatically during the CI/CD process. If it finds critical issues, the pipeline fails and blocks insecure images from being pushed further
Watch the full walkthrough here:
Why Vulnerability Scanning Matters
Container images often include operating system libraries, dependencies, and third-party packages. Any of these may contain known vulnerabilities. Without an automated scanning step, there is a chance of deploying applications with security risks. By adding Trivy to the pipeline, you catch risks early and save both time and effort in fixing them.
Workflow Overview
The GitHub Actions pipeline in this setup:
- Pull the latest code from the repository
- Build a Docker image from the project files
- Scan the image using Trivy
- Fails the workflow if it detects critical vulnerabilities
- Upload the scan report as an artifact for later review
The entire process runs automatically whenever code is pushed or a pull request is created.

Setting Up Image Scanning in GitHub Actions
For this guide, I have used a self-hosted runner. That choice allows tighter control over the runtime (Docker engine, CPU/RAM) and often results in quicker builds.
If you haven’t created a runner yet, do that first— using this guide.
Let’s break down the workflow step by step:
1. Triggering the Workflow
The pipeline is triggered on every push
or pull_request
to the main branch. This ensures that no new change goes unchecked.
2. Building the Docker Image
Pulls the latest code from the repository and builds a Docker image. For this example, the image is tagged as myapp:latest
.
3. Running the Trivy Scan
Uses Trivy to scan the image. The scan looks for vulnerabilities marked as HIGH and CRITICAL. Fails the job immediately if it finds critical issues.
4. Uploading the Scan Report
Even if the job fails, the scan report is uploaded as an artifact. This allows developers to download it later, review details of the vulnerabilities, and apply fixes.
Workflow File
name: Container Image Vulnerability Scan
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
security_scan:
runs-on: self-hosted
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker Image
run: |
sudo docker build -t myapp:latest .
- name: Generate Trivy Reports (Before Failing)
run: |
sudo trivy image --format json -o trivy-results.json myapp:latest
sudo trivy image --severity HIGH,CRITICAL myapp:latest | tee trivy-report.txt
- name: Upload Trivy Reports
uses: actions/upload-artifact@v4
with:
name: trivy-reports
path: |
trivy-report.txt
trivy-results.json
retention-days: 7
- name: Fail if Critical Vulnerabilities Found
run: |
sudo trivy image --exit-code 1 --severity CRITICAL myapp:latest
Running the Workflow
After you push changes, the workflow builds the image, runs the scan, and shows the results directly in the Actions tab. If critical vulnerabilities appear, the workflow fails, proving that the pipeline successfully blocked an insecure image.
You can then download the uploaded report, review the exact issues, and apply the necessary fixes.
Conclusion
Integrating Trivy with GitHub Actions turns container image scanning into an automatic step in the development workflow. Instead of pushing images with hidden risks, the pipeline stops them early and gives teams the chance to fix issues before release.
Making security checks part of CI/CD is no longer optional, it’s a habit every DevOps team should adopt.
You can explore the full workflow and other examples in my GitHub repository here: My Github Actions Code Repository
For a deeper dive, check out my playlist: GitHub Actions: Basics to Advanced