diff --git a/.github/workflows/docker-scout-scan.yml b/.github/workflows/docker-scout-scan.yml new file mode 100644 index 0000000..538f790 --- /dev/null +++ b/.github/workflows/docker-scout-scan.yml @@ -0,0 +1,93 @@ +name: Docker Scout PR Security Scan + +on: + pull_request: + branches: [ main ] + paths: + - 'Dockerfile' + - 'app/**' + - 'x/**' + - 'cmd/**' + - '.github/workflows/docker-scout-scan.yml' + workflow_dispatch: + +env: + IMAGE_NAME: ${{ github.repository }} + IMAGE_TAG: pr-${{ github.event.pull_request.number }} + +jobs: + docker-scout-scan: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + security-events: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_PAT }} + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE_NAME }} + tags: | + type=ref,event=pr + type=sha,prefix=pr-,format=short + + - name: Build Docker image (no push) + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: false + load: true + tags: ${{ steps.meta.outputs.tags }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Docker Scout - CVE Scan + uses: docker/scout-action@v1 + with: + command: cves + image: ${{ steps.meta.outputs.tags }} + only-severities: critical,high + exit-code: false + sarif-file: scout-report.sarif + + - name: Docker Scout - Compare to Latest + uses: docker/scout-action@v1 + if: github.event.pull_request.base.ref == 'main' + with: + command: compare + image: ${{ steps.meta.outputs.tags }} + to: ${{ env.IMAGE_NAME }}:latest + only-severities: critical,high + exit-code: true + + - name: Upload SARIF results to GitHub Security + uses: github/codeql-action/upload-sarif@v3 + if: always() + with: + sarif_file: scout-report.sarif + + - name: Generate vulnerability summary + if: always() + run: | + echo "## 🔍 Docker Scout Security Scan Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Image:** +${{ steps.meta.outputs.tags }}" + >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + docker scout cves ${{ steps.meta.outputs.tags }} --only-severity critical,high --format markdown >> $GITHUB_STEP_SUMMARY || echo "No critical/high vulnerabilities found! ✅" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/update-readme-scout.yml b/.github/workflows/update-readme-scout.yml new file mode 100644 index 0000000..b824668 --- /dev/null +++ b/.github/workflows/update-readme-scout.yml @@ -0,0 +1,56 @@ +name: Update README with Docker Scout Results + +on: + push: + branches: + - main + +jobs: + update-readme: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + token: ${{ secrets.REPO_PAT }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_PAT }} + + - name: Pull latest image + run: docker pull ${{ github.repository }}:latest || true + + - name: Docker Scout - CVE Scan + id: scout + uses: docker/scout-action@v1 + with: + command: cves + image: ${{ github.repository }}:latest + format: markdown + exit-code: false + + - name: Update README.md + run: | + awk '//{print;print "${{ steps.scout.outputs.markdown }}";f=1} //{f=0} !f{print}' README.md > README.md.tmp + mv README.md.tmp README.md + + - name: Commit and push if changed + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + git add README.md + if ! git diff --staged --quiet; then + git commit -m 'docs: update Docker Scout scan results [skip ci]' + git push + else + echo "No changes to commit." + fi