Files
james.maesandCodex 1a0964ef23 chore: enforce owned source copyright notices (#25)
* 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>
2026-11-01 12:41:00 -06:00

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