Container #73
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Container scanning + SBOM workflow. | |
| # | |
| # Runs on: | |
| # - PRs that touch Dockerfile / docker-compose.yml / .dockerignore | |
| # - Pushes to main (canary) | |
| # - Nightly (catches new CVE feeds against the published image) | |
| # - Release tags | |
| # | |
| # Aligned with NIST SP 800-190 §4.1–§4.5 and CISA SBOM Minimum Elements. | |
| name: Container | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - Dockerfile | |
| - docker-compose.yml | |
| - .dockerignore | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - Dockerfile | |
| - docker-compose.yml | |
| - .dockerignore | |
| schedule: | |
| - cron: '37 7 * * *' # nightly 07:37 UTC | |
| release: | |
| types: [published] | |
| permissions: | |
| contents: read | |
| jobs: | |
| build: | |
| name: Build image | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| image-id: ${{ steps.build.outputs.imageid }} | |
| steps: | |
| - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2 | |
| with: | |
| egress-policy: audit | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 | |
| - id: build | |
| uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 | |
| with: | |
| context: . | |
| push: false | |
| load: true | |
| tags: springtale-local:ci | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| trivy: | |
| name: Trivy | |
| runs-on: ubuntu-latest | |
| needs: build | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2 | |
| with: | |
| egress-policy: audit | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 | |
| - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 | |
| with: | |
| context: . | |
| push: false | |
| load: true | |
| tags: springtale-local:ci | |
| cache-from: type=gha | |
| - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| with: | |
| image-ref: springtale-local:ci | |
| format: sarif | |
| output: trivy.sarif | |
| severity: HIGH,CRITICAL | |
| exit-code: '1' | |
| # CRITICAL: in SARIF mode `severity` does NOT filter the report, and | |
| # `exit-code` then fires on ANY finding in it (including LOW). This | |
| # makes the severity filter apply to the SARIF + exit-code, so the | |
| # job gates only on HIGH/CRITICAL — not the LOW rust-dep advisories | |
| # (rand/lru/rpassword) which cargo-audit already tracks. | |
| limit-severities-for-sarif: true | |
| # Only fail on FIXABLE vulnerabilities — un-actionable upstream | |
| # base-OS CVEs (debian "wont-fix") can't be patched from here and are | |
| # picked up automatically when the distroless base is rebuilt. | |
| ignore-unfixed: true | |
| # vuln-only: secret scanning is owned by secrets.yml (gitleaks + | |
| # trufflehog) and false-positives on compiled-binary strings here. | |
| scanners: vuln | |
| - uses: github/codeql-action/upload-sarif@v3 | |
| if: always() | |
| with: | |
| sarif_file: trivy.sarif | |
| category: trivy | |
| grype: | |
| name: Grype | |
| runs-on: ubuntu-latest | |
| needs: build | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2 | |
| with: | |
| egress-policy: audit | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 | |
| - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 | |
| with: | |
| context: . | |
| push: false | |
| load: true | |
| tags: springtale-local:ci | |
| cache-from: type=gha | |
| - uses: anchore/scan-action@1638637db639e0ade3258b51db49a9a137574c3e # v6 | |
| with: | |
| image: springtale-local:ci | |
| fail-build: true | |
| severity-cutoff: high | |
| # Only fail on vulnerabilities with an available fix — mirrors | |
| # Trivy's ignore-unfixed. The base's libc6 HIGH/CRITICAL CVEs are all | |
| # debian "wont-fix" (CVE-2026-5450/5435/5928 + the disputed glibc | |
| # set), so they're un-actionable until distroless rebuilds. | |
| only-fixed: true | |
| output-format: sarif | |
| output-file: grype.sarif | |
| - uses: github/codeql-action/upload-sarif@v3 | |
| if: always() | |
| with: | |
| sarif_file: grype.sarif | |
| category: grype | |
| syft: | |
| name: Syft SBOM (image) | |
| runs-on: ubuntu-latest | |
| needs: build | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2 | |
| with: | |
| egress-policy: audit | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 | |
| - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 | |
| with: | |
| context: . | |
| push: false | |
| load: true | |
| tags: springtale-local:ci | |
| cache-from: type=gha | |
| - uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0 | |
| with: | |
| image: springtale-local:ci | |
| format: cyclonedx-json | |
| output-file: image-sbom.cdx.json | |
| - uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0 | |
| with: | |
| image: springtale-local:ci | |
| format: spdx-json | |
| output-file: image-sbom.spdx.json | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: container-sbom | |
| path: | | |
| image-sbom.cdx.json | |
| image-sbom.spdx.json | |
| retention-days: 90 |