Files
accounted/.github/workflows/docker-image-scan.yml
T
dependabot[bot] 26c5798b6e build(deps): bump docker/login-action from 3 to 4 (#696)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-25 12:39:26 +02:00

81 lines
3.2 KiB
YAML

name: Scheduled Image Vulnerability Scan
# The build pipeline (docker-publish.yml) builds and publishes the image but
# does NOT fail on CVEs — it stays green so deploys are deterministic. This
# workflow is the actual vulnerability gate: it re-scans the published `latest`
# image and fails (notifying repo admins) plus raises a Security-tab alert on a
# fixable CRITICAL/HIGH CVE, prompting a dependency or base-image bump.
#
# It fires on three triggers:
# 1. workflow_run — the moment "Build and Push Docker Image" completes, so a
# freshly published image is gated within the scan's own duration (minutes)
# rather than waiting up to 24h for the cron. This is what shrinks the
# vulnerable-image exposure window after every publish.
# 2. schedule (daily) — catches CVEs newly disclosed against an already-
# published image even when nothing was republished.
# 3. workflow_dispatch — run on demand from the Actions tab after a patch to
# confirm clean.
#
# NOTE: GitHub only runs `schedule` and `workflow_run` triggers from the default
# branch, so both start firing once this is merged to main.
on:
workflow_run:
workflows: ['Build and Push Docker Image']
types: [completed]
schedule:
# 06:17 UTC daily — off the hour to dodge cron congestion on GitHub.
- cron: '17 6 * * *'
workflow_dispatch: {}
env:
REGISTRY: ghcr.io
IMAGE_NAME: erp-mafia/gnubok
jobs:
scan:
runs-on: ubuntu-latest
# workflow_run fires even when the publish FAILED — there's no new image to
# gate in that case, so skip. schedule/workflow_dispatch carry no
# workflow_run payload, so the `!= 'workflow_run'` arm lets them through.
if: >-
github.event_name != 'workflow_run' ||
github.event.workflow_run.conclusion == 'success'
permissions:
contents: read
# Pull the published image from GHCR.
packages: read
# SARIF upload to the repo's "Security" tab.
security-events: write
steps:
- name: Log in to GHCR
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Scan published image with Trivy
uses: aquasecurity/trivy-action@v0.36.0
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
# Block on fixable CRITICAL/HIGH — the same policy the build pipeline
# used to enforce inline. It is safe to block here: a red scheduled
# run is a "go patch" notification, not a blocked deploy. ignore-unfixed
# keeps it actionable (only CVEs we can resolve by rebuilding fail).
severity: CRITICAL,HIGH
exit-code: '1'
ignore-unfixed: true
format: sarif
output: trivy-results.sarif
- name: Upload Trivy results to GitHub Security tab
# if: always() so findings still reach the Security tab even though the
# scan step above failed the run. Same category as docker-publish.yml so
# the two analyses share one alert set instead of duplicating.
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-results.sarif
category: trivy