mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
Merge pull request #725 from MBombeck/chore/transparency-ci
Scheduled CodeQL, Trivy and Scorecard workflows
This commit is contained in:
3 files changed
+297
No files matched your search
@@ -0,0 +1,73 @@
|
||||
name: CodeQL
|
||||
|
||||
# Static analysis for the TypeScript tree. This is GitHub's default setup
|
||||
# expressed as a workflow file rather than enabled from the repository
|
||||
# settings, so the query suite, the excluded paths and the schedule are
|
||||
# reviewable in the diff like everything else here.
|
||||
#
|
||||
# Deliberately NOT on `push: main`. The weekly run already analyses the
|
||||
# default branch, which is what keeps the Security tab current, and every
|
||||
# change reaches `main` through a pull request that is analysed on the way
|
||||
# in. Adding a push trigger would analyse the same tree a second time
|
||||
# minutes later for no additional signal.
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
schedule:
|
||||
# Mondays, 04:27 UTC. Off the hour so the run does not queue behind
|
||||
# everyone else's midnight cron.
|
||||
- cron: "27 4 * * 1"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: codeql-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyse javascript-typescript
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: read
|
||||
# Required to write the results into the repository's code-scanning
|
||||
# alerts. Free for public repositories.
|
||||
security-events: write
|
||||
# Required by the CodeQL action to read workflow run metadata.
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
# `build-mode: none` is the correct mode for JavaScript/TypeScript —
|
||||
# CodeQL extracts from source and needs neither a compile step nor
|
||||
# installed dependencies.
|
||||
#
|
||||
# The excluded paths are all generated or vendored output. Chief
|
||||
# among them is `src/generated`, the ~9 MB Prisma client with a
|
||||
# 224 KB inline schema literal in it: extracting that costs real
|
||||
# minutes and can produce nothing actionable, because nobody edits
|
||||
# it and the fix for anything found there is `pnpm prisma generate`.
|
||||
- name: Initialise CodeQL
|
||||
uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
|
||||
with:
|
||||
languages: javascript-typescript
|
||||
build-mode: none
|
||||
config: |
|
||||
paths-ignore:
|
||||
- src/generated
|
||||
- .next
|
||||
- dist
|
||||
- coverage
|
||||
- playwright-report
|
||||
- test-results
|
||||
- public
|
||||
|
||||
- name: Analyse
|
||||
uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
|
||||
with:
|
||||
category: "/language:javascript-typescript"
|
||||
@@ -0,0 +1,60 @@
|
||||
name: OpenSSF Scorecard
|
||||
|
||||
# Automated checks against the OpenSSF's supply-chain criteria: are Actions
|
||||
# pinned by SHA, is there a security policy, are dependencies updated
|
||||
# automatically, is the release pipeline signed, is there a fuzzing or a
|
||||
# static-analysis story. Most of what it looks for this repository already
|
||||
# does; the value is that it keeps looking after the person who set it up
|
||||
# has moved on to something else.
|
||||
#
|
||||
# `publish_results: true` sends the result to the OpenSSF's public API,
|
||||
# which is what makes the score citable by anyone evaluating the project
|
||||
# without asking for CI access. Nothing about the code or its contents
|
||||
# leaves; the checks read repository metadata and the workflow files.
|
||||
on:
|
||||
# Re-score when a branch-protection rule changes, since several checks
|
||||
# read exactly that.
|
||||
branch_protection_rule:
|
||||
schedule:
|
||||
# Tuesdays, 07:20 UTC.
|
||||
- cron: "20 7 * * 2"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Score supply-chain practices
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
permissions:
|
||||
# Write the findings into the repository's code-scanning alerts.
|
||||
security-events: write
|
||||
# Publish the result to the public API. This is an OIDC token
|
||||
# exchange, the same mechanism the release workflow uses for keyless
|
||||
# image signing; no long-lived credential is involved.
|
||||
id-token: write
|
||||
contents: read
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
# Scorecard reads the repository through the API, not through the
|
||||
# checkout, and leaving the token in `.git/config` would hand it
|
||||
# to anything else running in the job.
|
||||
persist-credentials: false
|
||||
|
||||
- name: Run analysis
|
||||
uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4
|
||||
with:
|
||||
results_file: scorecard-results.sarif
|
||||
results_format: sarif
|
||||
publish_results: true
|
||||
|
||||
- name: Upload results
|
||||
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
|
||||
with:
|
||||
sarif_file: scorecard-results.sarif
|
||||
category: scorecard
|
||||
@@ -0,0 +1,164 @@
|
||||
name: Trivy Scheduled Scan
|
||||
|
||||
# Two scans that the per-change gates cannot do, on a daily cadence.
|
||||
#
|
||||
# What already exists and is NOT repeated here:
|
||||
# - `security.yml` → `dependency-audit` runs `pnpm audit --prod` on every
|
||||
# push and pull request, blocking on HIGH/CRITICAL.
|
||||
# - `security.yml` → `docker-security` builds the image on a push to `main`
|
||||
# and runs `trivy image` against it, blocking on HIGH/CRITICAL.
|
||||
#
|
||||
# Both are change-triggered, and both answer "is this change safe". Neither
|
||||
# answers "is what we shipped last week still safe", because an advisory
|
||||
# published today lands against an image nobody is about to rebuild. That is
|
||||
# what the schedule is for. There is deliberately no push or pull_request
|
||||
# trigger: adding one would run the same scan the `docker-security` job
|
||||
# already ran, minutes later, on the same tree.
|
||||
on:
|
||||
schedule:
|
||||
# Daily, 05:17 UTC.
|
||||
- cron: "17 5 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: trivy-scheduled
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
filesystem:
|
||||
name: Lockfile (including dev dependencies)
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
# `pnpm audit --prod` is the blocking gate and it is scoped to
|
||||
# production dependencies on purpose: a dev-only advisory should not
|
||||
# stop a release. The gap that scoping leaves is that "dev dependency"
|
||||
# and "not in the image" are not the same statement.
|
||||
#
|
||||
# `pdfjs-dist` is the worked example. It sits in `devDependencies`,
|
||||
# and `src/lib/documents/rasterize-pdf.ts` imports it at runtime, so
|
||||
# Next's standalone output tracing copies it into the production
|
||||
# image. `pnpm audit --prod` cannot see it. This scan can: without
|
||||
# the flag Trivy reads 627 packages out of `pnpm-lock.yaml`, with it
|
||||
# 1455, and `pdfjs-dist` is only in the second set.
|
||||
#
|
||||
# Trivy's own `--help` lists the flag as supported for npm, yarn and
|
||||
# gradle. It works on `pnpm-lock.yaml` too; the help text is behind
|
||||
# the parser. Verified against this repository before this workflow
|
||||
# was written, and worth re-checking if the package count ever
|
||||
# collapses back to the production figure.
|
||||
#
|
||||
# Report-only, and that is a deliberate choice rather than a soft
|
||||
# one. The findings this widening surfaces are overwhelmingly
|
||||
# transitive dev-tool advisories with fixes available upstream;
|
||||
# failing the run on them from day one produces a red badge that gets
|
||||
# muted within a week, and a muted signal is worse than none. The
|
||||
# SARIF upload puts every finding in the repository's code-scanning
|
||||
# alerts, which persist, notify, and can be triaged one at a time.
|
||||
# The blocking answer to "does this ship" stays where it is, in
|
||||
# `security.yml`.
|
||||
- name: Trivy filesystem scan
|
||||
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
|
||||
env:
|
||||
# No action input maps to `--include-dev-deps`; Trivy reads every
|
||||
# flag from a `TRIVY_`-prefixed environment variable, so this is
|
||||
# the documented way to reach it through the action.
|
||||
TRIVY_INCLUDE_DEV_DEPS: "true"
|
||||
with:
|
||||
scan-type: fs
|
||||
scan-ref: .
|
||||
scanners: vuln
|
||||
format: sarif
|
||||
output: trivy-filesystem.sarif
|
||||
severity: "CRITICAL,HIGH,MEDIUM"
|
||||
limit-severities-for-sarif: true
|
||||
exit-code: "0"
|
||||
# Generated Prisma client. Nobody edits it, the fix for anything
|
||||
# found in it is `pnpm prisma generate`, and it is ~9 MB.
|
||||
skip-dirs: src/generated
|
||||
|
||||
- name: Upload results
|
||||
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
|
||||
with:
|
||||
sarif_file: trivy-filesystem.sarif
|
||||
category: trivy-filesystem
|
||||
|
||||
published-image:
|
||||
name: Published image
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
security-events: write
|
||||
|
||||
steps:
|
||||
# The `docker-security` job scans an image it just built from the
|
||||
# current `main`. This one scans the image operators actually pull,
|
||||
# which is the one built from the last release tag and unchanged
|
||||
# since. The two answer different questions and the gap between them
|
||||
# widens every day a release stays out.
|
||||
#
|
||||
# Trivy resolves the multi-arch manifest to the runner's platform, so
|
||||
# this covers `linux/amd64`. The arm64 manifest shares every
|
||||
# application layer and differs only in native binaries.
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# `.trivyignore` lives at the repository root and Trivy reads it
|
||||
# automatically, so the suppressions the blocking gate already
|
||||
# carries apply here too and the two scans cannot disagree about
|
||||
# what is accepted.
|
||||
- name: Checkout for .trivyignore
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
# Fails on CRITICAL only. A critical advisory against the image
|
||||
# self-hosters are running right now is worth a red badge and a
|
||||
# notification; HIGH goes to code scanning with everything else,
|
||||
# because the release pipeline already refuses to publish an image
|
||||
# carrying one and anything that appears here appeared after the
|
||||
# fact.
|
||||
- name: Trivy published-image scan
|
||||
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
|
||||
with:
|
||||
scan-type: image
|
||||
image-ref: ghcr.io/mbombeck/healthlog:latest
|
||||
scanners: vuln
|
||||
format: sarif
|
||||
output: trivy-published-image.sarif
|
||||
severity: "CRITICAL,HIGH,MEDIUM"
|
||||
limit-severities-for-sarif: true
|
||||
exit-code: "0"
|
||||
|
||||
- name: Upload results
|
||||
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
|
||||
with:
|
||||
sarif_file: trivy-published-image.sarif
|
||||
category: trivy-published-image
|
||||
|
||||
# Separate table pass so the SARIF upload above always runs, even
|
||||
# when this one fails the job. A scan whose failure suppresses its
|
||||
# own report is a scan you have to re-run by hand to read.
|
||||
- name: Fail on a critical finding in the published image
|
||||
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
|
||||
with:
|
||||
scan-type: image
|
||||
image-ref: ghcr.io/mbombeck/healthlog:latest
|
||||
scanners: vuln
|
||||
format: table
|
||||
severity: "CRITICAL"
|
||||
exit-code: "1"
|
||||
Reference in new issue
Block a user