name: Docker Image Security Scan on: schedule: # Run daily at 2 AM UTC - cron: '0 2 * * *' push: branches: - main tags: - 'v*.*.*' workflow_dispatch: env: REGISTRY: ghcr.io IMAGE_NAME: valknarness/awesome-app jobs: scan: runs-on: ubuntu-latest permissions: contents: read packages: read security-events: write steps: - name: Checkout repository uses: actions/checkout@v4 - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Pull latest image run: | docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest || echo "Image not found, will skip scan" - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest format: 'sarif' output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' - name: Upload Trivy results to GitHub Security uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: 'trivy-results.sarif' - name: Run Trivy vulnerability scanner (table output) uses: aquasecurity/trivy-action@master with: image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest format: 'table' severity: 'CRITICAL,HIGH,MEDIUM' - name: Generate scan summary if: always() run: | echo "### Security Scan Results :shield:" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Image:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Scan Date:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "Check the Security tab for detailed vulnerability reports." >> $GITHUB_STEP_SUMMARY