Skip to content

chore: supply-chain hardening - #20

Open
erik1o6 wants to merge 2 commits into
masterfrom
security-hardening
Open

erik1o6 wants to merge 2 commits into
masterfrom
security-hardening

Conversation

@erik1o6

@erik1o6 erik1o6 commented Apr 30, 2026

Copy link
Copy Markdown

Summary

End-to-end supply-chain hardening for the oracle-checks repo. Two commits:

  1. Initial hardening — exact pins, Corepack, Node pin, .npmrc knobs, frozen-lockfile installs, lockfile-drift CI gate, npm audit gate, Dependabot cooldown, least-priv workflow perms, GH Actions pinned to SHAs.
  2. Follow-ups — Node 22 (20 EOL today), min-release-age=7, oracle-sdk pinned to a SHA, narrower check-adapters perms, audit gate covers dev tree, npm audit fix zeroes the prior 10 findings.

Controls applied

  • 1. Direct deps exact-pinned (apps)
  • 2. packageManager pinned via Corepack — npm@10.9.8
  • 3. Node pinned — .nvmrc=22, engines.node>=22, engine-strict=true
  • 4. .npmrc hardened — audit-level=high, engine-strict=true, save-exact=true, fund=false, min-release-age=7
  • 5. Frozen-lockfile installs — npm ci in both workflows
  • 6. Lockfile-drift CI gate
  • 7. Audit gate — npm audit --audit-level=high (no --omit=dev)
  • 8. Dependabot cooldown — 7-day for npm and github-actions
  • 10. Workflow least-priv — ci.yml is contents: read; check-adapters.yml is contents: read at workflow level with contents: write only on the job that needs to push
  • 11. GH Actions pinned to SHAs — actions/checkout, actions/setup-node, jakejarvis/s3-sync-action

Skipped:

    1. Dockerfile hygiene — N/A (no Dockerfile)
  • O1–O5 — N/A or out of scope for this pass

Notable design choices

  • @objectivelabs/oracle-sdk is pinned to a commit SHA (41d9222415…) instead of floating #main. The prebuild script that re-pulled #main on every build was removed. The hourly check-adapters workflow still installs #main ephemerally at runtime — that's its job — but it commits only data/, so the SHA pin in master stays stable. To bump the SDK, open a PR.
  • check-adapters.yml runs as contents: read at workflow level; the single job retains contents: write because it commits data/ and submodule changes. Narrows the scope inherited by composite/reusable actions.
  • min-release-age=7 is in days (verified against npm cli source — default: null, hint: '<days>', type: [null, Number]). Requires npm 10.9+; that's why packageManager is bumped to 10.9.8.

Test plan

  • npm ci clean on Node 22 + npm 10.9.x
  • npm run build produces working output on Node 22
  • npm audit --audit-level=high reports found 0 vulnerabilities
  • CI green on this branch (PR job will run)
  • After merge, the 13 Dependabot findings on master (8 high, 4 moderate, 1 low) close

erik1o6 added 2 commits April 30, 2026 20:07
Apply the standard hardening recipe (mirrors euler-vault-creator PR #50,
adapted for npm):

- package.json: pin all deps to exact versions; pin packageManager
  (npm@10.8.2) and engines.node (>=20). Remove unused express dep
  (eliminates 4 prod audit findings: express/body-parser/path-to-regexp/qs).
- .nvmrc: pin Node to 20 (matches existing check-adapters workflow).
- .npmrc: audit-level=high, engine-strict=true, save-exact=true, fund=false.
- .github/dependabot.yml: weekly npm + github-actions updates with 7-day
  release cooldown.
- .github/workflows/ci.yml: new least-priv PR validation workflow —
  npm ci, lockfile-drift gate, and npm audit --audit-level=high --omit=dev.
- .github/workflows/check-adapters.yml: SHA-pin actions/checkout,
  actions/setup-node, jakejarvis/s3-sync-action; switch setup-node to
  read .nvmrc.

Lint is intentionally not gated in CI — repo has pre-existing lint
errors on master that are out of scope for this hardening pass.

Note: the prebuild step still pulls @objectivelabs/oracle-sdk from
github:euler-xyz/oracle-sdk#main on every build, which floats by
design. That's a separate concern from this hardening pass.
- Bump Node 20 → 22 (.nvmrc, engines.node, @types/node) — Node 20 hits
  EOL 2026-04-30.
- Bump packageManager to npm@10.9.8 and add min-release-age=7 to .npmrc
  (install-time release-age gate; requires npm 10.9+).
- Pin @objectivelabs/oracle-sdk to commit SHA
  (41d9222415ec276b89d1d82bc166c4b6ccff2d0b) instead of floating #main,
  and drop the prebuild script that re-pulled #main on every build.
  The check-adapters workflow remains the canonical update path —
  it ephemerally installs #main at runtime but does not commit the bump.
- check-adapters.yml: workflow-level permissions now contents:read;
  job-level retains contents:write (needed for the data/ + submodule
  push). Narrows the scope inherited by reusable/composite actions.
- ci.yml: drop --omit=dev from the audit gate so dev-tree CVEs are not
  silently skipped.
- npm audit fix: resolved all 10 prior findings (rollup, glob, picomatch,
  minimatch, brace-expansion, ajv, flatted, js-yaml, yaml, @isaacs/brace-expansion).
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