feat(ci): add app CI gate, container security scanning, and least-privilege permissions #31

Merged
KofTwentyTwo merged 1 commits from ci/security-hardening into main 2026-07-29 16:10:17 +00:00
KofTwentyTwo commented 2026-07-29 16:04:58 +00:00 (Migrated from github.com)

Summary

  • Add a fast App CI gate (app-ci.yml): npm ci / npm run lint / npm run build on Node 22, running on every PR and push to main, separate from the slower Docker build.
  • Add a Trivy container scan job (ci.yml, trivy-scan, runs after build) that scans the built image for CRITICAL/HIGH CVEs, uploads SARIF to GitHub code scanning (Security tab), and fails the job only on CRITICAL findings (HIGH is reported, not blocking) so a solo maintainer isn't stalled by noise.
  • Workflow hygiene: every workflow now has an explicit least-privilege top-level permissions: contents: read, with packages: write (GHCR push) and security-events: write (SARIF upload) elevated only on the jobs that need them. All third-party actions are pinned to version tags.
  • Dockerfile: strip npm/npx/yarn/corepack from the final runtime stage. The container's entrypoint is node server.js only — none of that tooling is ever invoked at runtime — and it was the source of the only CRITICAL (CVE-2026-59873, tar) and all 5 HIGH findings Trivy found in the current image. Removing it resolves those findings without touching the node:22-alpine base image tag or the app's runtime behavior.
  • dependabot.yml already covered both npm and github-actions ecosystems — no change needed there.
  • codeql.yml already has least-privilege permissions (actions: read, contents: read, security-events: write) — left as-is per the brief.

Verified locally before opening this PR

  • npm ci && npm run lint && npm run build — all pass (lint: 0 errors, 3 pre-existing warnings; build: succeeds).
  • docker build — image builds and the container serves GET / with 200 OK.
  • Built the image and ran aquasecurity/trivy against it directly: before the Dockerfile change — 1 CRITICAL + 5 HIGH (all in npm's bundled tar/brace-expansion/picomatch/sigstore, base-image tooling not used at runtime); after — 0 CRITICAL, 0 HIGH.
  • Existing GHCR build/push behavior is unchanged: push still gated to github.event_name != 'pull_request', same tags (latest, ${{ github.sha }}).

Test plan

  • build check passes (required by branch protection, unchanged behavior)
  • App CI / lint-and-build passes
  • Build and Push Nuncio Website Container / trivy-scan passes and shows 0 CRITICAL
  • SARIF results appear under the repo's Security > Code scanning tab after merge
## Summary - Add a fast **App CI gate** (`app-ci.yml`): `npm ci` / `npm run lint` / `npm run build` on Node 22, running on every PR and push to `main`, separate from the slower Docker build. - Add a **Trivy container scan** job (`ci.yml`, `trivy-scan`, runs after `build`) that scans the built image for CRITICAL/HIGH CVEs, uploads SARIF to GitHub code scanning (Security tab), and fails the job only on CRITICAL findings (HIGH is reported, not blocking) so a solo maintainer isn't stalled by noise. - **Workflow hygiene**: every workflow now has an explicit least-privilege top-level `permissions: contents: read`, with `packages: write` (GHCR push) and `security-events: write` (SARIF upload) elevated only on the jobs that need them. All third-party actions are pinned to version tags. - **Dockerfile**: strip `npm`/`npx`/`yarn`/`corepack` from the final runtime stage. The container's entrypoint is `node server.js` only — none of that tooling is ever invoked at runtime — and it was the source of the only CRITICAL (`CVE-2026-59873`, `tar`) and all 5 HIGH findings Trivy found in the current image. Removing it resolves those findings without touching the `node:22-alpine` base image tag or the app's runtime behavior. - `dependabot.yml` already covered both `npm` and `github-actions` ecosystems — no change needed there. - `codeql.yml` already has least-privilege permissions (`actions: read`, `contents: read`, `security-events: write`) — left as-is per the brief. ## Verified locally before opening this PR - `npm ci && npm run lint && npm run build` — all pass (lint: 0 errors, 3 pre-existing warnings; build: succeeds). - `docker build` — image builds and the container serves `GET /` with `200 OK`. - Built the image and ran `aquasecurity/trivy` against it directly: **before** the Dockerfile change — 1 CRITICAL + 5 HIGH (all in npm's bundled `tar`/`brace-expansion`/`picomatch`/`sigstore`, base-image tooling not used at runtime); **after** — 0 CRITICAL, 0 HIGH. - Existing GHCR build/push behavior is unchanged: push still gated to `github.event_name != 'pull_request'`, same tags (`latest`, `${{ github.sha }}`). ## Test plan - [ ] `build` check passes (required by branch protection, unchanged behavior) - [ ] `App CI / lint-and-build` passes - [ ] `Build and Push Nuncio Website Container / trivy-scan` passes and shows 0 CRITICAL - [ ] SARIF results appear under the repo's Security > Code scanning tab after merge
github-advanced-security[bot] commented 2026-07-29 16:07:44 +00:00 (Migrated from github.com)

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. ### What Enabling Code Scanning Means: - The 'Security' tab will display more code scanning analysis results (e.g., for the default branch). - Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. - You will be able to see the analysis results for the pull request's branch on this [overview](/KofTwentyTwo/nuncio-website/security/code-scanning?query=pr%3A31+is%3Aopen) once the scans have completed and the checks have passed. For more information about GitHub Code Scanning, check out [the documentation](https://docs.github.com/code-security/code-scanning/introduction-to-code-scanning/about-code-scanning).
Sign in to join this conversation.