* chore(standards): preserve owned-source copyright notices Add accurate repository copyright and license comments to 50 owned source/build/configuration files. Preserve existing holders, upstream wrappers, legal payloads and schema/data exemptions. Exact inverse-byte reconstruction and applicable parser/token/AST checks prove comment-only changes; existing relevant regressions pass. Co-Authored-By: Codex (GPT-6) <noreply@openai.com> Signed-off-by: James Maes <james@kof22.com> * chore: enforce owned source copyright notices Check real leading comments against explicit repository provenance and retain existing native style gates. Co-Authored-By: Codex GPT-6 <noreply@openai.com> Signed-off-by: James Maes <james@kof22.com> --------- Signed-off-by: James Maes <james@kof22.com> Co-authored-by: Codex (GPT-6) <noreply@openai.com>
211 lines
8.9 KiB
YAML
211 lines
8.9 KiB
YAML
# Copyright 2026 Kingsrook, LLC
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
# Local copy of KofTwentyTwo/standards security.yml at
|
|
# fdf5ed029603c938615a32b1beca3628b8787945 (v0.1.2).
|
|
# Scanner pins and security gates are preserved. SCA scans Maven-selected runtime
|
|
# coordinates with ui-demo enabled; independent POM resolution can choose different versions.
|
|
name: security
|
|
|
|
on:
|
|
pull_request:
|
|
push:
|
|
branches: [main]
|
|
schedule:
|
|
- cron: "23 6 * * 1"
|
|
workflow_dispatch:
|
|
|
|
workflow_call:
|
|
|
|
permissions: {}
|
|
|
|
concurrency:
|
|
group: security-${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
|
|
jobs:
|
|
secrets:
|
|
name: security / secrets
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 15
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- name: Checkout (full history)
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
|
|
# The container runs as root over a workspace owned by the runner user; git
|
|
# refuses such repositories unless they are marked safe, which the
|
|
# GIT_CONFIG_* variables do without a writable global config.
|
|
- name: Gitleaks (every commit)
|
|
uses: docker://ghcr.io/gitleaks/gitleaks:v8.30.1@sha256:c00b6bd0aeb3071cbcb79009cb16a60dd9e0a7c60e2be9ab65d25e6bc8abbb7f
|
|
env:
|
|
GIT_CONFIG_COUNT: "1"
|
|
GIT_CONFIG_KEY_0: safe.directory
|
|
GIT_CONFIG_VALUE_0: "*"
|
|
with:
|
|
args: git /github/workspace --redact --verbose --exit-code 1 --no-banner
|
|
|
|
sca:
|
|
name: security / sca
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 25
|
|
permissions:
|
|
contents: read
|
|
security-events: write # upload SARIF results to code scanning
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
# Resolve the actual deployed profile, including frontend assets.
|
|
# Do not restore an Actions cache in this security job.
|
|
- name: Set up Java
|
|
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
|
with:
|
|
distribution: temurin
|
|
java-version: '21'
|
|
- name: Test inventory guards
|
|
run: python3 .github/scripts/test-maven-inventory.py
|
|
- name: Resolve selected runtime graph and SBOM
|
|
run: |
|
|
set -euo pipefail
|
|
bash ./mvnw --batch-mode --no-transfer-progress -Pui-demo \
|
|
dependency:list -DincludeScope=runtime -DoutputFile=target/runtime-dependencies.txt \
|
|
org.cyclonedx:cyclonedx-maven-plugin:2.9.1:makeBom \
|
|
-DincludeCompileScope=true -DincludeRuntimeScope=true \
|
|
-DincludeProvidedScope=false -DincludeSystemScope=false -DincludeTestScope=false \
|
|
-DoutputFormat=json -DoutputName=printing-runtime -Dcyclonedx.skipAttach=true
|
|
python3 .github/scripts/check-maven-inventory.py target/runtime-dependencies.txt target/printing-runtime.json
|
|
|
|
# SARIF for code scanning carries MEDIUM and above for visibility; the gate
|
|
# below fails only on the configured severities (HIGH and CRITICAL by default).
|
|
- name: Trivy dependency inventory and SARIF
|
|
env:
|
|
TRIVY_IMAGE: ghcr.io/aquasecurity/trivy:0.75.0@sha256:af6acf9a6b85dfe389a1941505c0ce9efef52a4719635e1a962f022a3d855daa
|
|
run: |
|
|
set -euo pipefail
|
|
docker run --rm -v "$PWD:/src" "$TRIVY_IMAGE" \
|
|
sbom --scanners vuln --severity MEDIUM,HIGH,CRITICAL \
|
|
--cache-dir /src/.trivycache --list-all-pkgs --format json \
|
|
--output /src/trivy.json --exit-code 0 /src/target/printing-runtime.json
|
|
python3 .github/scripts/check-maven-inventory.py target/runtime-dependencies.txt target/printing-runtime.json trivy.json
|
|
docker run --rm -v "$PWD:/src" "$TRIVY_IMAGE" \
|
|
convert --format sarif --output /src/trivy.sarif /src/trivy.json
|
|
# OSV reads the identical verified Maven graph, without another resolver.
|
|
cp target/printing-runtime.json printing.cdx.json
|
|
|
|
- name: Upload SARIF to code scanning
|
|
# Fork pull requests get a read-only token, so only same-repository runs upload.
|
|
if: always() && hashFiles('trivy.sarif') != '' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
|
|
uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
|
with:
|
|
sarif_file: trivy.sarif
|
|
category: trivy-sca
|
|
|
|
# Malicious packages (OpenSSF malicious-packages feed, OSV `MAL-` IDs) are a
|
|
# different threat from CVEs and are not in Trivy's database, so OSV-Scanner
|
|
# checks the same resolved graph as a CycloneDX SBOM. This avoids re-parsing
|
|
# the upstream Maven parent whose published revision placeholder OSV rejects.
|
|
# Any MAL- finding fails the job; an empty SBOM is also a failure.
|
|
- name: OSV-Scanner (malicious packages)
|
|
env:
|
|
OSV_IMAGE: ghcr.io/google/osv-scanner:v2.6.0@sha256:afd838850ac1a0fcc15ff4a041dc9ba11123c3f0d2666217a5f0fcf9222b55fa
|
|
run: |
|
|
set -euo pipefail
|
|
status=0
|
|
docker run --rm -v "$PWD:/src:ro" "$OSV_IMAGE" scan source --lockfile /src/printing.cdx.json --all-packages --format json > osv.json || status=$?
|
|
# 0: nothing found, 1: vulnerabilities found. Other statuses fail closed.
|
|
case "$status" in
|
|
0|1) ;;
|
|
*) echo "::error title=OSV-Scanner failed::exit code $status"; exit 1 ;;
|
|
esac
|
|
python3 .github/scripts/check-maven-inventory.py target/runtime-dependencies.txt target/printing-runtime.json trivy.json --osv osv.json
|
|
malicious=$(jq -r '
|
|
[ .results[]?.packages[]?
|
|
| .package as $p
|
|
| .vulnerabilities[]?
|
|
| select((.id | startswith("MAL-")) or ((.aliases // []) | any(startswith("MAL-"))))
|
|
| "\(.id) \($p.ecosystem)/\($p.name)@\($p.version)" ]
|
|
| unique | .[]' osv.json)
|
|
if [[ -n "$malicious" ]]; then
|
|
while IFS= read -r finding; do
|
|
echo "::error title=Malicious package::$finding"
|
|
done <<< "$malicious"
|
|
exit 1
|
|
fi
|
|
echo "No dependency is flagged as malicious."
|
|
|
|
- name: Gate on vulnerable dependencies
|
|
env:
|
|
TRIVY_IMAGE: ghcr.io/aquasecurity/trivy:0.75.0@sha256:af6acf9a6b85dfe389a1941505c0ce9efef52a4719635e1a962f022a3d855daa
|
|
run: |
|
|
set -euo pipefail
|
|
docker run --rm -v "$PWD:/src:ro" "$TRIVY_IMAGE" \
|
|
convert --severity HIGH,CRITICAL --format table --exit-code 1 /src/trivy.json
|
|
|
|
- name: Retain dependency scan evidence
|
|
if: always()
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
with:
|
|
name: maven-runtime-security-inventory
|
|
path: |
|
|
target/runtime-dependencies.txt
|
|
target/printing-runtime.json
|
|
trivy.json
|
|
osv.json
|
|
if-no-files-found: error
|
|
|
|
workflows:
|
|
name: security / workflows
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 10
|
|
permissions:
|
|
contents: read
|
|
security-events: write # upload SARIF results to code scanning
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Set up uv
|
|
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
with:
|
|
enable-cache: false
|
|
|
|
- name: zizmor (SARIF)
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: uvx zizmor@1.30.1 --format sarif --min-severity low . > zizmor.sarif || true
|
|
|
|
- name: Upload SARIF to code scanning
|
|
if: always() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
|
|
uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
|
with:
|
|
sarif_file: zizmor.sarif
|
|
category: zizmor
|
|
|
|
# GH_TOKEN enables zizmor's online audits (impostor commits, known-vulnerable
|
|
# actions, ref confusion); the read-only job token is enough.
|
|
- name: zizmor gate (medium and above)
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: uvx zizmor@1.30.1 --min-severity medium .
|
|
|
|
- name: actionlint
|
|
env:
|
|
ACTIONLINT_VERSION: 1.7.12
|
|
ACTIONLINT_SHA256: 8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8
|
|
run: |
|
|
set -euo pipefail
|
|
archive="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
|
|
curl -fsSLO "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/${archive}"
|
|
echo "${ACTIONLINT_SHA256} ${archive}" | sha256sum --check --strict
|
|
tar -xzf "${archive}" actionlint
|
|
./actionlint -color
|