Skip to content

Container

Container #73

Workflow file for this run

# 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