Skip to content

Conversation

@josecelano
Copy link
Member

Closes #251

Overview

Implements a GitHub Actions workflow that uses Trivy to scan Docker images for vulnerabilities. This initial implementation uses a hardcoded list of images and provides immediate security coverage.

Changes

1. GitHub Actions Workflow (.github/workflows/docker-security-scan.yml)

Created a new workflow with two jobs:

Scan Project-Built Images

  • Builds and scans 2 project-built images:
    • torrust-tracker-deployer/provisioned-instance
    • torrust-tracker-deployer/ssh-server

Scan Third-Party Images

  • Scans 4 third-party images used in docker-compose:
    • torrust/tracker:develop
    • mysql:8.0
    • grafana/grafana:11.4.0
    • prom/prometheus:v3.0.1

Workflow Features:

  • ✅ Scans for HIGH/CRITICAL vulnerabilities only
  • ✅ Fails builds when vulnerabilities detected (exit-code: 1)
  • ✅ Uploads results to GitHub Security tab (SARIF format)
  • ✅ Runs on push to main/develop
  • ✅ Runs on PRs affecting Docker files
  • ✅ Runs daily at 6 AM UTC
  • ✅ Supports manual triggering

Notes:

2. README Update

Added workflow badge to display scan status.

Testing

  • ✅ Pre-commit checks passed (./scripts/pre-commit.sh)
  • ✅ YAML linting passed
  • ✅ All unit tests passed
  • ✅ E2E tests passed

Future Work

This is Phase 1 of the security scanning epic. Phase 2 (#252) will:

  • Dynamically detect images from environment configuration
  • Eliminate need for manual updates when images change
  • Integrate with show command to list scanned images

Related

@github-advanced-security
Copy link

This pull request sets up GitHub code scanning for this repository. Once the scans have completed and the checks have passed, the analysis results for this pull request branch will appear on this overview. Once you merge this pull request, the 'Security' tab will show more code scanning analysis results (for example, for the default branch). Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. For more information about GitHub code scanning, check out the documentation.

@josecelano josecelano requested a review from da2ce7 December 23, 2025 17:51
@josecelano josecelano marked this pull request as draft December 23, 2025 18:34
@josecelano josecelano marked this pull request as ready for review December 23, 2025 19:23
@josecelano josecelano marked this pull request as draft December 23, 2025 20:10
@josecelano
Copy link
Member Author

Viewing Security Scan Results

The workflow successfully uploads SARIF results to GitHub Security, but the default Security tab view filters by is:open branch:main, which means results from PR branches are not visible in the default view.

How to View Results

  • For this PR: https://github.com/torrust/torrust-tracker-deployer/security/code-scanning?query=pr:256+is:open
  • For PR branch: /security/code-scanning?query=is:open+branch:251-implement-basic-trivy-scanning-workflow
  • After merging: Results will appear in the default Security tab view (/security/code-scanning?query=is:open+branch:main)

All six SARIF uploads are completing successfully:

  • ✅ docker-project-provisioned-instance
  • ✅ docker-project-ssh-server
  • ✅ docker-third-party-mysql-8.0
  • ✅ docker-third-party-torrust-tracker-develop
  • ✅ docker-third-party-grafana-grafana-11.4.0
  • ✅ docker-third-party-prom-prometheus-v3.0.1

This is standard GitHub behavior for code scanning - PR results are filtered separately from main branch results.

@josecelano
Copy link
Member Author

Viewing Security Scan Results

The workflow successfully uploads SARIF results to GitHub Security, but the default Security tab view filters by 'is:open branch:main', which means results from PR branches are not visible in the default view.

How to View Results

All six SARIF uploads are completing successfully with unique categories. This is standard GitHub behavior for code scanning - PR results are filtered separately from main branch results.

- Add comment in workflow explaining filter behavior
- Add section in ADR explaining how to view results by branch/PR
- Add PR comment with direct links to view scan results

The default Security tab filters by 'is:open branch:main' which
hides PR branch results. Users must use specific PR/branch filters
to see results before merging to main.
@josecelano
Copy link
Member Author

ACK 40dd234

@josecelano josecelano marked this pull request as ready for review December 23, 2025 20:31
@josecelano
Copy link
Member Author

Design Decision: Upload Steps Pattern

The upload job currently uses 6 individual steps instead of a matrix. This is intentional for Phase 1 (hardcoded images).

Why Not Matrix Now?

Matrix would require duplicating the image list:

  • Scan jobs already define matrices for the 6 images
  • Upload job would need to duplicate that list
  • Two sources of truth = synchronization issues
  • Refactoring effort would be throwaway work

Future: Dynamic Array Passing (Issue #252)

Phase 2 will implement dynamic image detection, where:

  • Scan jobs output a JSON array of scanned images
  • Upload job consumes that array via fromJSON(needs.scan.outputs.images)
  • Single source of truth: scan jobs determine what gets uploaded
  • Zero manual maintenance when images change

Example for Phase 2:

scan-images:
  outputs:
    scanned_images: ${{ steps.collect.outputs.images }}

upload-sarif:
  needs: scan-images
  strategy:
    matrix:
      image: ${{ fromJSON(needs.scan-images.outputs.scanned_images) }}

Decision Rationale

Keep current implementation because:

  • ✅ Simple, explicit, easy to debug
  • ✅ Works perfectly for hardcoded lists
  • ✅ Avoids premature optimization
  • ✅ Phase 2 refactoring will be more comprehensive anyway

References:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Basic Trivy Scanning Workflow

2 participants