Skip to content

Security Wave 5 - CI/CD security audit workflow, Dependabot, Node 22, firebase-tools pin#125

Merged
dev-mansonthomas merged 4 commits into
masterfrom
security/wave-5-cicd-hardening
May 15, 2026
Merged

Security Wave 5 - CI/CD security audit workflow, Dependabot, Node 22, firebase-tools pin#125
dev-mansonthomas merged 4 commits into
masterfrom
security/wave-5-cicd-hardening

Conversation

@dev-mansonthomas
Copy link
Copy Markdown
Owner

Security Wave 5 — CI/CD hardening

Implements Wave 5 of docs/security-audit-redquest.md.

Changes

5.1 — .github/workflows/security-audit.yml

  • Triggers: pull_request to master, weekly Monday cron (0 6 * * 1), manual workflow_dispatch.
  • permissions: contents: read → least-privilege GITHUB_TOKEN.
  • SHA-pinned actions (40-char commit SHA, not tag — tj-actions mitigation):
    • actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
    • actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
  • Node version from .nvmrc (node-version-file), no duplication.
  • Ratchet vs baseline instead of --audit-level=high: the plan's original --audit-level=high would fail every PR (67 pre-existing high vulns from Angular 10). The job parses npm audit --json and compares per-severity counts to docs/security-baseline-2026-05-15-post-wave1.json, failing only if a PR introduces new vulnerabilities.

5.2 — Local deploy hardening

  • New .nvmrc pins Node 22.
  • gcp-deploy.sh:
    • set -euo pipefail → fail-fast on errors / unset vars.
    • Drop hardcoded /usr/local/opt/node@14/bin PATH override.
    • Startup check: Node major must be >= 22, otherwise exit with a hint.
    • Replace global firebase invocations with npx --yes firebase-tools@15 (pinned major, allows patches, prevents surprise v16). The @13 of the original plan is obsolete; latest stable is 15.18.0.

5.4 — .github/dependabot.yml

  • Weekly Monday 06:00 Europe/Paris for both npm and github-actions.
  • Open-PR caps: 5 (npm), 3 (github-actions).
  • Grouped updates (npm): angular, typescript, firebase, testing.

5.3 — Branch protection (manual UI action, NOT covered by this PR)

Checklist documented in docs/security-audit-redquest.md under "5.3 — Checklist Branch Protection". Required steps:

  1. https://github.com/dev-mansonthomas/RedQuest/settings/branches → Add rule for master.
  2. Require PR + 1 approval + dismiss stale approvals.
  3. Require status check audit (the job name from this workflow) — visible in the UI after the first run on master.
  4. Disallow force-push and branch deletion.

This must wait until the workflow has executed at least once so the audit check appears in the dropdown.

Documentation

  • README.md synced: Node 22 prerequisite, npx firebase-tools@15 as canonical invocation.
  • docs/security-audit-redquest.md updated with the actual implementation choices (ratchet vs baseline, SHA pinning rationale, firebase-tools@15).

Verification

  • bash -n gcp-deploy.sh → OK.
  • node ratchet logic dry-run against current npm audit and post-Wave 1 baseline → OK: no growth vs baseline (4 critical / 67 high / 62 moderate / 14 low, unchanged).
  • YAML validated: js-yaml.load() on both .github/workflows/security-audit.yml and .github/dependabot.yml parses without error.
  • No source code or dependency changes → Karma + build status unchanged from master.

Out of scope

  • 5.3 branch protection is a manual GitHub UI step. The PR documents it but does not (cannot) apply it.
  • Workflow's first run will happen when this PR is opened. The ratchet should pass since the baseline file is also in this PR's base (master).

Rollback

Four small commits, each independently revertable:

  • 73dac76 deploy script + .nvmrc
  • 747c7a2 README sync
  • 57f6b10 .github/ (workflow + dependabot)
  • 77f58db audit doc Wave 5 section

Related

Wave 5.2 of docs/security-audit-redquest.md - hardens the local deploy pipeline.

Changes to gcp-deploy.sh:

- Add 'set -euo pipefail' so a failed sub-command aborts the deploy instead of continuing.

- Drop the hardcoded '/usr/local/opt/node@14/bin' PATH override. The project now requires Node >= 22 (see .nvmrc). A startup check on node major version exits 1 with a hint if the shell points at an older Node.

- Replace global 'firebase' / 'firebase deploy' invocations with 'npx --yes firebase-tools@15 ...'. Pinning the major prevents a future v16 from silently breaking the deploy, while still allowing patches. Removes the previous dependency on a globally-installed firebase-tools whose version was effectively unknown.

New .nvmrc pins Node 22 for nvm / fnm / asdf users.

No bundle/test impact: deploy script and version manifest only.
Sync README with Wave 5.2 changes:

- Node prerequisite reflects '.nvmrc' (>=22) instead of the legacy Node 14 path.

- Firebase CLI is no longer required as a global install; document 'npx firebase-tools@15' as the canonical invocation, matching gcp-deploy.sh.

- Troubleshooting section: replace the Node 14 PATH advice with an 'nvm use' / brew install hint.
Wave 5.1 + 5.4 of docs/security-audit-redquest.md.

.github/workflows/security-audit.yml:

- Triggers: pull_request to master, weekly Monday cron, manual workflow_dispatch.

- 'permissions: contents: read' minimises the GITHUB_TOKEN scope (least privilege).

- Both third-party actions are pinned by 40-character commit SHA, not by tag: actions/checkout@de0fac2... (v6.0.2) and actions/setup-node@48b55a0... (v6.4.0). This mitigates the tj-actions class of attacks where a malicious tag move would swap the action code; Dependabot keeps the SHAs current via the github-actions ecosystem.

- Node version comes from .nvmrc via 'node-version-file', not duplicated in YAML.

- 'npm audit --audit-level=high' would fail every PR (67 pre-existing high vulns from Angular 10). Replaced with a ratchet: the job parses 'npm audit --json' and compares per-severity counts against 'docs/security-baseline-2026-05-15-post-wave1.json', failing only if a PR introduces NEW vulnerabilities. Pre-existing ones do not block.

.github/dependabot.yml:

- Weekly Monday 06:00 Europe/Paris schedule for both npm and github-actions ecosystems.

- Open-PR caps: 5 (npm), 3 (github-actions) to keep review load bounded.

- npm grouping: angular (@angular/*, @angular-devkit/*, @ngtools/*), typescript (typescript, ts-*, @types/*), firebase (firebase, @angular/fire), testing (karma*, jasmine*, @types/jasmine*). Groups reduce noise by consolidating coordinated bumps.
…klist

Update the implementation plan with Wave 5 outcomes:

- 5.1/5.2/5.4: marked as done with the actual implementation notes (ratchet vs baseline instead of '--audit-level=high', SHA pinning details, firebase-tools@15 instead of obsolete @13).

- 5.3 'Branch protection': documented as a manual GitHub UI action with a step-by-step checklist (require PR review, 1 approval minimum, dismiss stale approvals, require the 'audit' status check, disallow force-push and deletion). The required status check name is 'audit' (the job name in security-audit.yml); it becomes available in the GitHub UI after the workflow's first run.
@dev-mansonthomas dev-mansonthomas merged commit 7c207ec into master May 15, 2026
1 check passed
@dev-mansonthomas dev-mansonthomas deleted the security/wave-5-cicd-hardening branch May 15, 2026 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant