Skip to content

thehyve/vulnerability-scanning

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

34 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ›‘οΈ vulnerability-scanning

Reusable GitHub Actions workflows to scan Docker images for vulnerabilities and report findings as GitHub Issues.


πŸ“‹ Table of contents


πŸ—ΊοΈ Overview

This repository provides two independent reusable workflows:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           generate-image-list               β”‚
β”‚                                             β”‚
β”‚  Compose files ─┐                           β”‚
β”‚  Dockerfiles    β”œβ”€ scan_docker_images.py ──►│──► docker_images.env
β”‚  *.yml / *.yamlβ”€β”˜                           β”‚    (committed to repo)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚
                          β”‚  (or bring your own docker_images.env)
                          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              vuln-scanning                  β”‚
β”‚                                             β”‚
β”‚  docker_images.env ──► Trivy / Snyk scan ──►│──► GitHub Issues
β”‚                                             β”‚    (HIGH / CRITICAL)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ” generate-image-list β€” Scans your repository for Docker image references in Compose files and Dockerfiles, and writes them to a docker_images.env file that is committed back to your repo. Use this when you want image discovery to be fully automated.

πŸ”¬ vuln-scanning β€” Reads a docker_images.env file, scans each image for vulnerabilities using Trivy or Snyk, and creates or updates GitHub Issues for every HIGH or CRITICAL finding. If your repository already maintains its own image list, you can use this workflow on its own without generate-image-list.

The workflows are designed to be used together or independently, depending on your setup.


βš™οΈ How it works

  1. Image discovery (generate-image-list workflow)
    scan_docker_images.py walks the caller's repository and finds every Docker image reference in:

    • docker-compose.yml, *.yml, *.yaml – lines matching image: <ref>
    • Dockerfile, Dockerfile.* – lines matching FROM <ref>

    References that use environment-variable substitution (${VAR}) are skipped because they are already sourced from the .env file. The discovered images are written to docker_images.env (or a custom path) and committed back to the caller's repository.

  2. Vulnerability scanning (vuln-scanning workflow)
    Reads a docker_images.env file containing *_IMAGE variables (produced by step 1, or maintained manually), iterates over every image, and scans each one with either Trivy or Snyk. Results are saved as a JSON artifact.

  3. Issue management (create-issue action)
    Compares the scan results against existing open GitHub Issues (filtered by a caller-supplied label). For each vulnerable image:

    • If no issue exists β†’ a new issue is created with HIGH / CRITICAL labels and a list of CVE IDs.
    • If an issue already exists β†’ a new comment is added with the latest scan results.

πŸ” Reusable workflows

Both workflows are independent and can be called on their own. Use generate-image-list only if you want image discovery to be automated; skip it if you already maintain a docker_images.env file yourself.

1. πŸ” generate-image-list

Scans the caller's repository and commits docker_images.env.

Caller workflow example:

jobs:
  generate-image-list:
    uses: thehyve/vulnerability-scanning/.github/workflows/generate-image-list.yml@main
    secrets: inherit          # forwards GH_PAT for private submodules (optional)
    with:
      output-file: docker_images.env   # optional, this is the default
      vuln-scanning-ref: main          # optional, pin to a specific ref

Inputs:

Input Required Default Description
output-file No docker_images.env Path (relative to repo root) to write the image list to
vuln-scanning-ref No main Branch, tag, or SHA of the thehyve/vulnerability-scanning repo to use

Secrets:

Secret Required Description
GH_PAT Conditional A Personal Access Token. Required only when the caller's repo contains private submodules in other repositories. Falls back to the built-in GITHUB_TOKEN automatically when absent.

Creating a PAT (when needed):

Option A β€” Fine-grained PAT (recommended)
  1. Go to GitHub β†’ Settings β†’ Developer settings β†’ Personal access tokens β†’ Fine-grained tokens
  2. Click Generate new token
  3. Under Repository access, select the relevant repositories and grant:
    • Calling repo (e.g. opentargets-automation): Contents β†’ Read and write
    • Each private submodule repo: Contents β†’ Read
  4. Click Generate token and copy the value
Option B β€” Classic PAT (simpler, broader access)
  1. Go to GitHub β†’ Settings β†’ Developer settings β†’ Personal access tokens β†’ Tokens (classic)
  2. Click Generate new token
  3. Select the repo scope (grants full read/write access to all private repos on your account)
  4. Click Generate token and copy the value

Then store the token as a repository secret named GH_PAT:

  1. Go to your repository β†’ Settings β†’ Secrets and variables β†’ Actions
  2. Click New repository secret
  3. Name: GH_PAT, Value: the token you copied

2. πŸ”¬ vuln-scanning

Scans images listed in an .env file and creates GitHub Issues for findings.

Caller workflow example:

jobs:
  vuln-scanning:
    uses: thehyve/vulnerability-scanning/.github/workflows/vuln-scanning.yml@main
    secrets:
      token: ${{ secrets.GITHUB_TOKEN }}
      snyk-token: ${{ secrets.SNYK_TOKEN }}   # only required when scan-option is 'snyk'
    with:
      scan-option: trivy
      env-file-path: docker_images.env
      tag: vulnerability
      assignee-user: octocat          # optional
      scan-report: scan_result.json   # optional

Inputs:

Input Required Default Description
scan-option Yes trivy Scanner to use: trivy or snyk
env-file-path Yes Path to the .env file containing *_IMAGE variables
tag Yes Label applied to all created GitHub Issues (used to correlate issues between runs)
assignee-user No (none) GitHub username to assign created issues to
scan-report No scan_result.json Path to write the raw scan output (JSON)

Secrets:

Secret Required Description
token Yes GitHub token used to create/update issues (typically GITHUB_TOKEN)
snyk-token No Snyk API token (required when scan-option is snyk)

🐍 scan_docker_images.py (local use)

The script can also be run locally from the root of any repository:

# Scan the current directory and write docker_images.env
python3 scan_docker_images.py

# Write to a custom path
OUTPUT_FILE=infra/images.env python3 scan_docker_images.py

What is scanned:

  • *.yml / *.yaml – image: <ref> directives (YAML anchors are supported)
  • Dockerfile / Dockerfile.* – FROM <ref> directives (scratch and variable references are skipped)

Skipped directories: .git, .mypy_cache, node_modules, __pycache__, .venv


🏷️ Variable naming convention

Given an image reference the script derives an environment-variable name as follows:

Step Example
Original reference ghcr.io/opentargets/platform-api:25.4.2
Strip tag ghcr.io/opentargets/platform-api
Take last path component (repo name) platform-api
Replace non-word characters with _ platform_api
Upper-case PLATFORM_API
Append _IMAGE PLATFORM_API_IMAGE

When multiple images share the same base name (e.g. two different tags of the same image), the tag is incorporated into both variable names to keep them unique:

# Found in: docker-compose.yml
CLICKHOUSE_SERVER_23_3_IMAGE=clickhouse/clickhouse-server:23.3

# Found in: docker-compose.prod.yml
CLICKHOUSE_SERVER_25_8_2_29_IMAGE=clickhouse/clickhouse-server:25.8.2.29

Version-prefix tags (e.g. mysql:8 alongside mysql:8.0) are automatically merged β€” the shorter prefix is absorbed into the more specific tag.


🎫 Issue lifecycle

Condition Action
πŸ†• Vulnerability found, no existing issue New issue created with HIGH / CRITICAL label(s) and CVE list
πŸ”„ Vulnerability found, issue already exists Comment added to the existing issue with updated scan timestamp and CVE list
βœ… No HIGH or CRITICAL vulnerabilities for an image No issue created or updated

Issues are matched by title (Vulnerability detected in <image>) and the caller-supplied tag label, so scans from different projects do not interfere with each other.


πŸš€ End-to-end example

Both workflows together (image discovery + scanning):

# .github/workflows/scheduled-vuln-scan.yml
name: Scheduled vulnerability scan

on:
  schedule:
    - cron: "0 6 * * 1"   # every Monday at 06:00 UTC
  workflow_dispatch:

jobs:
  generate-image-list:
    uses: thehyve/vulnerability-scanning/.github/workflows/generate-image-list.yml@main
    secrets: inherit

  vuln-scanning:
    needs: generate-image-list
    uses: thehyve/vulnerability-scanning/.github/workflows/vuln-scanning.yml@main
    secrets:
      token: ${{ secrets.GITHUB_TOKEN }}
    with:
      scan-option: trivy
      env-file-path: docker_images.env
      tag: vuln-scan
      assignee-user: your-github-username

Scanning only (repository already has its own docker_images.env):

# .github/workflows/scheduled-vuln-scan.yml
name: Scheduled vulnerability scan

on:
  schedule:
    - cron: "0 6 * * 1"   # every Monday at 06:00 UTC
  workflow_dispatch:

jobs:
  vuln-scanning:
    uses: thehyve/vulnerability-scanning/.github/workflows/vuln-scanning.yml@main
    secrets:
      token: ${{ secrets.GITHUB_TOKEN }}
    with:
      scan-option: trivy
      env-file-path: docker_images.env
      tag: vuln-scan
      assignee-user: your-github-username

About

GitHub action to report vulnerabilities as issues

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages