Security Scan (SIAX Cloud) / gitleaks (push) Failing after 21s
CI (SIAX Cloud) / security (push) Successful in 27s
Security Scan (SIAX Cloud) / trivy (push) Failing after 47s
CI (SIAX Cloud) / quality (push) Successful in 3m28s
Security Scan (SIAX Cloud) / license-inventory (push) Successful in 8m59s
BACKLOG P0-13: next.config.mjs now sets HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, and a same-origin CSP on every route. Previously the only security header came from Vercel's platform default (HSTS) -- nothing was set by the app itself, so it would have silently disappeared on cutover to Coolify/Traefik. Verified at runtime (curl -I against a production build), not just that the build compiles. BACKLOG P0-16: Trivy in security.yml/nightly.yml now actually fails the build on HIGH/CRITICAL findings (`--exit-code 1`) instead of the previous `--exit-code 0` (purely advisory, never blocked a merge). Verified locally against this repo's real dependency tree -- 19 HIGH findings currently exist in pnpm-lock.yaml (next.js, postcss, sharp, nanoid), several in next.js itself relating to middleware/auth bypass. See PR description: this is expected to turn the security.yml `trivy` job red until those are bumped in a follow-up -- that's the fix working as intended, not a regression, but it needs a human decision on timing given the sibling auth-gate PR (#11). `services/scrapers/` stays explicitly excluded from the scan (--skip-dirs) -- that tree is a dated, deliberate keep-decision under active review in a separate thread (BACKLOG P3-3) and is out of scope here. BACKLOG P0-19: dedicated gitleaks job added to security.yml, full git history (--log-opts=--all), pinned + checksum-verified binary. Verified locally against this repo's actual history first (81 commits, no leaks) so this blocking gate doesn't open red on day one. BACKLOG P1-14: SBOM (CycloneDX) + license inventory (`pnpm licenses list`) generated as informational, non-blocking build artifacts. actions/checkout, actions/setup-node, actions/cache, actions/upload-artifact all pinned to commit SHA (was floating @v4 tags) across every workflow file, Trivy/gitleaks pinned to specific released versions instead of floating install scripts. cosign image-signing explicitly NOT added -- there is no container-registry publish step in this repo's CI to attach a signature to yet (Coolify builds directly from git); flagging as a real follow-up once that pipeline exists. BACKLOG P1-15: explicit `permissions: contents: read` + `concurrency` added to every workflow that lacked them (only .github/workflows/ci.yml already had concurrency). Pinned pnpm-store cache added to ci.yml's quality job. Root CODEOWNERS added (`* @sax3l`) so Gitea has someone to assign once required-approvals is turned on (separate repo-settings change, not a file change). The "doctor step" part of P1-15 is added in the follow-up repo- hygiene PR, alongside the `siax:doctor` script it invokes.
95 lines
3.8 KiB
YAML
95 lines
3.8 KiB
YAML
name: Security Scan (SIAX Cloud)
|
|
|
|
# BACKLOG P0-16, P0-19, P1-14: this used to run Trivy with `--exit-code 0`,
|
|
# i.e. purely advisory -- findings never blocked a merge. It now fails the
|
|
# build for real on HIGH/CRITICAL, plus a dedicated gitleaks step (REPO-15:
|
|
# the only prior secret sweep was hand-rolled regex, not a real
|
|
# secret-scanning tool), plus an SBOM + license inventory as build artifacts.
|
|
#
|
|
# `services/scrapers/` is excluded from the Trivy scan (--skip-dirs). That
|
|
# tree (waf_bypass.py, engine*.py, curl_cffi/cloudscraper/nodriver) is a
|
|
# deliberate, dated, user-level keep decision under active review in a
|
|
# separate thread (docs/compliance/BACKLOG.md P3-3) -- explicitly out of
|
|
# scope for this workflow change, and it must not be the reason this gate
|
|
# starts failing for everyone. Every other path in the repo is now enforced
|
|
# for real, including the rest of services/ (the FastAPI engine itself).
|
|
on:
|
|
push:
|
|
branches: ["**"]
|
|
pull_request:
|
|
workflow_dispatch:
|
|
schedule:
|
|
- cron: "0 5 * * 1" # weekly Monday re-scan
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: security-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
trivy:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
- name: Install Trivy (pinned)
|
|
run: |
|
|
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.73.0
|
|
- name: Trivy fs scan (vuln + secrets -- BLOCKING)
|
|
run: |
|
|
trivy fs --scanners vuln,secret --severity HIGH,CRITICAL \
|
|
--skip-dirs services/scrapers \
|
|
--exit-code 1 .
|
|
- name: SBOM (CycloneDX, informational artifact -- BACKLOG P1-14)
|
|
if: always()
|
|
run: |
|
|
trivy fs --format cyclonedx --output sbom.cdx.json --skip-dirs services/scrapers .
|
|
- name: Upload SBOM
|
|
if: always()
|
|
continue-on-error: true # informational artifact; must never block the blocking scan above
|
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
with:
|
|
name: sbom-cyclonedx
|
|
path: sbom.cdx.json
|
|
retention-days: 90
|
|
|
|
gitleaks:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
with:
|
|
fetch-depth: 0 # gitleaks needs full history, not just the tip commit
|
|
- name: Install gitleaks (pinned + checksum-verified)
|
|
run: |
|
|
curl -sSL -o gitleaks.tar.gz https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz
|
|
echo "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb gitleaks.tar.gz" | sha256sum -c -
|
|
tar -xzf gitleaks.tar.gz gitleaks
|
|
sudo mv gitleaks /usr/local/bin/gitleaks
|
|
- name: gitleaks scan (full history -- BLOCKING)
|
|
run: gitleaks detect --source . --log-opts="--all" --redact --verbose
|
|
|
|
license-inventory:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
node-version: "22"
|
|
- name: Enable corepack + pin pnpm@9
|
|
run: |
|
|
corepack enable
|
|
corepack prepare pnpm@9 --activate
|
|
- name: Install (frozen lockfile)
|
|
run: pnpm install --frozen-lockfile
|
|
- name: License inventory (informational -- BACKLOG P1-14)
|
|
run: |
|
|
pnpm licenses list --json > licenses.json || true
|
|
pnpm licenses list
|
|
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
continue-on-error: true # informational artifact; must never block CI
|
|
with:
|
|
name: license-inventory
|
|
path: licenses.json
|
|
retention-days: 90
|