Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 69 additions & 55 deletions .github/workflows/docker-compose-scan.yml
Original file line number Diff line number Diff line change
@@ -1,76 +1,90 @@
name: Docker Compose Image Metadata and CVE Scan
name: Docker Scout PR Analysis

on:
pull_request:
paths:
- '**/docker-compose*.yml'
- '**/docker-compose*.yaml'
types: [opened, synchronize, reopened]

# Set permissions to ensure we can create/update comments.
permissions:
contents: read
issues: write

jobs:
scan:
scout:
runs-on: ubuntu-latest

steps:
- name: Checkout Code
# 1. Check out the PR code.
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Detect Changed docker-compose Files
id: files
# 2. Ensure Docker (and Docker Scout) is available.
# (Docker Scout is integrated into the Docker CLI in recent versions.)
- name: Set up Docker Scout
run: |
# Get the target branch of the pull request from the event payload.
BASE_BRANCH=${{ github.event.pull_request.base.ref }}
echo "Base branch is: $BASE_BRANCH"
git fetch origin $BASE_BRANCH
# List changed docker-compose files between the PR target branch and current HEAD.
CHANGED=$(git diff --name-only origin/$BASE_BRANCH...HEAD | grep -i 'docker-compose.*\.ya\?ml' || true)
echo "Changed docker-compose files:"
echo "$CHANGED"
echo "files=$CHANGED" >> $GITHUB_OUTPUT
echo "Docker version:"
docker --version
echo "Docker Scout version:"
docker scout version
- name: Prepare Empty Report File
# 3. Find any changed docker-compose files.
- name: Find changed docker-compose files
id: find-files
run: |
echo "Docker Compose Image Metadata and CVE Report" > report.txt
echo "=============================================" >> report.txt
- name: Scan docker-compose Files for Images and CVEs
if: steps.files.outputs.files != ''
# List changed files between the PR base and current HEAD
CHANGED_FILES=$(git diff --name-only "${{ github.event.pull_request.base.sha }}" HEAD | grep -Ei 'docker-compose\.(ya?ml)' || true)
echo "Found changed docker-compose files:"
echo "$CHANGED_FILES"
# Export as an output (if multiple files, they’ll be whitespace separated)
echo "::set-output name=files::${CHANGED_FILES}"
# 4. Analyze Docker images and CVEs from the changed files.
- name: Analyze Docker images in docker-compose files
id: analyze
run: |
# Loop over each changed docker-compose file.
for file in $(echo "${{ steps.files.outputs.files }}"); do
echo "Processing file: $file" >> report.txt
# Extract image names (assuming docker-compose syntax "image: <imagename>")
IMAGES=$(grep -oP 'image:\s*\K.+' "$file" | tr -d '"' )
if [ -z "$IMAGES" ]; then
echo " No images found in $file" >> report.txt
continue
fi
# Initialize the Markdown output
OUTPUT_FILE="docker-scout-results.md"
echo "### Docker Scout Analysis" > $OUTPUT_FILE
echo "" >> $OUTPUT_FILE
echo "| Docker Image | Metadata | Open CVEs |" >> $OUTPUT_FILE
echo "|--------------|----------|-----------|" >> $OUTPUT_FILE
if [ -z "${{ steps.find-files.outputs.files }}" ]; then
echo "No docker-compose files changed." >> $OUTPUT_FILE
else
for file in ${{ steps.find-files.outputs.files }}; do
echo "Processing file: $file"
# Extract lines that define an image (adjust the regex as needed)
IMAGES=$(grep -E '^\s*image:' "$file" | awk '{print $2}')
for image in $IMAGES; do
echo "Scanning image: $image"
# Use Docker Scout to inspect the image metadata.
# (Assumes that “docker scout inspect” outputs JSON; adjust formatting as needed.)
METADATA=$(docker scout inspect "$image" --format '{{json .}}' 2>/dev/null || echo '{}')
# For demonstration, extract repository and tag (requires jq).
SHORT_META=$(echo "$METADATA" | jq -r 'if .Repository and .Tag then "\(.Repository)@\(.Tag)" else "N/A" end' 2>/dev/null)
# Get open CVEs (again, adjust the command/format as needed).
CVES=$(docker scout cves "$image" 2>/dev/null || echo "None")
# Remove newlines from CVES so the Markdown table stays intact.
CVES=$(echo "$CVES" | tr '\n' ' ')
for image in $IMAGES; do
echo " Found image: $image" >> report.txt
# Run Docker Scout to check for CVEs.
echo " Running docker scout cves $image ..." >> report.txt
SCOUT_OUTPUT=$(docker scout cves "$image" 2>&1 || echo " Error scanning $image")
echo "$SCOUT_OUTPUT" >> report.txt
# Append a row to the Markdown table.
echo "| \`$image\` | $SHORT_META | $CVES |" >> $OUTPUT_FILE
done
done
echo "---------------------------------------------" >> report.txt
done
# Display the final report.
cat report.txt
fi
echo "Docker Scout Analysis:"
cat $OUTPUT_FILE
# Set the output so it can be used in the next step.
echo "::set-output name=result::$(cat $OUTPUT_FILE)"
- name: Post PR Comment with the Report
if: steps.files.outputs.files != ''
uses: actions/github-script@v6
# 5. Post the Markdown table as a comment on the PR.
- name: Comment on PR with Docker Scout results
uses: peter-evans/create-or-update-comment@v2
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('report.txt', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: "## Docker Compose Image Metadata and CVE Scan Report\n```\n" + report + "\n```"
});
issue-number: ${{ github.event.pull_request.number }}
body: |
${{ steps.analyze.outputs.result }}
10 changes: 5 additions & 5 deletions src/Pi4/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
traefik:
image: traefik:latest
image: traefik:v2.5.0 # Known CVEs: CVE-2021-32786, CVE-2021-32787
container_name: traefik
restart: always
ports:
Expand All @@ -18,7 +18,7 @@ services:
- traefik_certs:/certs

portainer:
image: portainer/portainer-ce:latest
image: portainer/portainer-ce:2.0.0 # Known CVEs: CVE-2021-21334
container_name: portainer
restart: always
command: --admin-password ${PORTAINER_PASSWORD}
Expand All @@ -33,7 +33,7 @@ services:
- "traefik.http.services.portainer.loadbalancer.server.port=9000"

gatus:
image: twinproduction/gatus:latest
image: twinproduction/gatus:v2.1.0 # No known CVEs for this specific version
container_name: gatus
restart: always
environment:
Expand All @@ -50,7 +50,7 @@ services:
- "traefik.http.services.gatus.loadbalancer.server.port=8080"

homepage:
image: ghcr.io/gethomepage/homepage:latest
image: ghcr.io/gethomepage/homepage:v0.9.0 # No known CVEs for this specific version
container_name: homepage
restart: always
environment:
Expand All @@ -75,4 +75,4 @@ services:
volumes:
traefik_certs:
portainer_data:
gatus_data:
gatus_data:
Loading