chore: supply chain update - 4#122
Conversation
Converge all 13 package.json files onto a single exact-pinned toolchain target — latest stable on npm: @graphprotocol/graph-cli ^0.97.0 / ^0.98.1 -> 0.98.1 @graphprotocol/graph-ts ^0.38.0 / ^0.38.2 -> 0.38.2 matchstick-as 0.5.0 / ^0.6.0 -> 0.6.0 All carets stripped to exact pins for deterministic resolutions. Three subgraphs (staking, predict-omen, predict-polymarket) were already on the 0.98.1 line; the other 9 subgraphs + root are bumped up to converge. Verification (full local CI sequence on Node 22 + yarn 1.22): yarn install --frozen-lockfile : all 13 paths "Already up-to-date" yarn graph codegen + test : all 12 subgraphs pass liquidity 23 tests passed tokenomics-eth 3 tests passed governance 12 tests passed legacy-mech-fees 15 tests passed predict-omen 19 tests passed predict-polymarket 96 tests passed babydegen-optimism 10 tests passed liquidity-l2 15 tests passed staking 18 tests passed tokenomics-l2 8 tests passed service-registry 13 tests passed new-mech-fees 15 tests passed ---------------------------------------- TOTAL 247 Matchstick tests, all green yarn audit delta is modest (latest stable is only 0.98.1; bigger jumps not yet stable on npm). Net change across paths: -13 High advisories on heaviest paths, +3 on three paths (matchstick-as 0.6 transitive), unchanged on the rest. Real wins of this PR are version consistency and exact-pin determinism, not advisory clearance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 3: prevent regression — every future PR auto-checked. Closes T5 future-leak detection. Lands remaining hygiene without bundling with PR1 (CI hardening) or PR2 (dep bump). Workflows added: - .github/workflows/supply-chain.yml — audit + install-hooks + lockfile-lint matrix over 13 paths, with all-checks-passed aggregator. Advisory-only at first; promote to required-status in branch protection when team is ready. - .github/workflows/gitleaks.yml — secret scan on every push + PR. Gitleaks 8.30.1 with SHA-256 verified binary download (551f6fc83ea457...). Verified against townhall-kpis pin and upstream checksums.txt. Scripts added: - scripts/audit.mjs — wraps `yarn audit --json` with allowlist suppression. Critical: invoked as `yarn audit:prod` not `yarn audit` (yarn 1.x's built-in shadows same-named scripts). - scripts/audit-install-hooks.mjs — diffs node_modules install-hooks against .supply-chain/install-hooks.allowlist; drift in either direction (new hook OR removed hook) fails the job. Allowlists baselined: - .supply-chain/audit-allowlist.json — 23 high/critical advisories baselined as transitive of @graphprotocol/graph-cli (latest stable 0.98.1 doesn't refresh them). Each entry has reason + added + review (90-day cadence). - .supply-chain/install-hooks.allowlist — empty: graph-cli's transitives are pure JS, no install hooks at root level. Configuration: - .nvmrc → 22.18.0 (resolves prior Node 20/24 drift between test.yaml and deploy-subgraph.yaml workflows). - root package.json: engines.node "22.x", packageManager "yarn@1.22.22", and audit:* script aliases. - Both workflows updated to node-version-file: .nvmrc and Corepack activation with version assertion. Documentation: - SUPPLY-CHAIN-SECURITY.md — threat model (T1-T5), secrets inventory, Dependabot alerts setup (one-time UI toggle — no .github/dependabot.yml since user wants silent alerts only, no PR spam from version-update bot), audit/install-hooks/ lockfile-lint/gitleaks rationale, response playbook, repo-specific watches (graph-cli upstream, SUBGRAPH_STUDIO_KEY rotation). - CLAUDE.md — supply-chain section pointing at the docs + the audit:prod naming-collision warning + the org-wide blast radius note. - .github/CODEOWNERS — expanded to cover .supply-chain/, scripts/, SUPPLY-CHAIN-SECURITY.md, .nvmrc. Pre-merge verification (locally on Node 22 + yarn 1.22): yarn audit:prod : OK (23 allowlisted, no unlisted) yarn audit:install-hooks : OK (0 allowlisted) lockfile-lint x 13 paths : ✔ No issues detected Failure-mode simulations (all gates fail-closed correctly): - Empty allowlist → 23 unlisted advisories blocked ✓ - Stale install-hook entry → drift detected, exit 1 ✓ - codeload.github.com source → invalid host detected, exit 1 ✓ Branch protection settings change is OUT of scope for this PR; the new gates will run advisory until manually promoted to required-status (separate Settings UI change post-merge). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR Review:
|
| File | Change |
|---|---|
package.json |
+resolutions block: immutable ^5.1.5, cross-spawn ^7.0.6, semver ^7.5.2 |
.supply-chain/audit-allowlist.json |
-3 entries (1117068 immutable, 1112921 semver, 1104664 cross-spawn) |
yarn.lock |
Consolidates 4 semver@* entries → 7.7.4; bumps immutable 5.1.4→5.1.5; collapses cross-spawn@7.0.3→7.0.6; drops dead lru-cache@6 + yallist@4 (orphaned by the semver bump) |
Strengths
- 1:1 pairing — every resolution is matched by an allowlist removal. Net reduction in suppressions, no orphan entries left behind. The "stale entry" warning in
scripts/audit.mjs:153-157confirms the script would catch any forgotten removal. - Resolutions block carries the rationale — the inline
//comment explains why picomatch/minimatch/glob were skipped (multiple majors in tree). Future-you (or another reviewer) won't have to re-derive that. - Caret floors pinned at the fix version, not above —
^7.5.2for semver, even though the installed version is 7.7.4. Correct: pinning the floor at the actual fix lets the lockfile pick a fresher version freely without making the resolution itself the gate. - No install-hook drift expected —
immutable,cross-spawn,semver,lru-cache,yallistare all script-free;.supply-chain/install-hooks.allowlistis empty and should stay empty. - Lockfile is genuinely smaller — 71 lines removed vs. 12 added. The consolidation is real, not just rewriting.
Concerns
1. Scope: subgraph yarn.locks still ship the vulnerable versions (worth addressing or calling out)
The supply-chain audit job (.github/workflows/supply-chain.yml:16-34) runs yarn audit:prod once, at root — its name says so explicitly: "Dependency audit (root tree)". The 12 subgraph yarn.lock files still contain the unpatched versions:
subgraphs/*/yarn.lock: immutable@5.1.4 / cross-spawn@7.0.3 / semver@7.3.5
These are the lockfiles consumed when each subgraph runs yarn install for codegen/build/test/deploy. The PR description ("clear 3 audit advisories") is technically accurate for the gated tree, but the same vulnerable code still lands in every subgraph's node_modules. This is a pre-existing gap (introduced when supply-chain CI was scoped to root in update-3), not something this PR caused — but since the resolutions exist now, it'd be cheap to propagate them. Two options:
- Fix here: copy
resolutionsinto all 12 subgraph package.jsons +yarn installin each to refresh locks. Mechanical, but 24 file changes. - Defer + document: leave a note in
SUPPLY-CHAIN-SECURITY.mdthat the audit gate covers root only and subgraph trees aren't currently audited.
I'd lean toward the first — same advisories, same fix, the work is pure copy-paste, and it eliminates the divergence between what CI gates and what actually deploys.
2. "//": "..." key inside resolutions may trip Yarn 1
Yarn 1 treats every key in resolutions as a package selector and emits a warning (sometimes an error in --frozen-lockfile mode) for unknown selectors. The standard JSON-comment hack works in dependencies because Yarn ignores unresolved deps, but resolutions is parsed differently. Worth a quick local check:
yarn install --frozen-lockfileIf it warns or fails, move the comment out of resolutions — either inline above the block as a regular "//" field at the top level of package.json, or into SUPPLY-CHAIN-SECURITY.md where the rest of the supply-chain rationale already lives. (The doc-in-the-file rationale is genuinely useful — I'd rather see it relocated than dropped.)
3. Minor: the comment lists the multi-major exclusions but the allowlist still references them
The remaining allowlist entries for picomatch/minimatch/glob/etc. don't cite the "multiple majors" reasoning — they all say "latest stable graph-cli (0.98.1) does not refresh this advisory". Both reasons are true, but a future reviewer trying to clear those entries with another resolution will only see the upstream-bump reason and miss the more fundamental "can't, would break installs" constraint that's documented over in package.json. Optional: cross-reference the package.json comment from those allowlist entries' reason field, or add the multi-major note to those entries.
Verdict
The mechanism is sound and the diff is clean. #2 is the one I'd want resolved before merge (5-second check), #1 is a judgment call about scope creep vs. closing a gate-vs-reality gap, #3 is polish.
…blic token addresses A history scan with gitleaks 8.18 / default ruleset reports 54 hits across 374 commits. All 54 are false positives — every redacted secret resolves to a public on-chain Optimism ERC20 contract address (USDC, USDT, DAI, WETH, etc.) hardcoded into babydegen mapping logic for decimals/symbol branching, plus one example token address in subgraphs/liquidity/README.md inside a Dune SQL snippet. This config extends the upstream default ruleset and adds a single allowlist scoped by BOTH path and regex shape (0x + exactly 40 hex chars), so secrets with any other shape — or in any other path — still flag. Verification (gitleaks 8.18.0, full history --log-opts="--all"): - Without config: 54 hits. - With config: 0 hits. - Positive test (synthetic AWS / Slack / sk_live_* fixtures in a temp dir outside the allowlisted paths): all 4 leaks still detected. The allowlist does not silence real secrets. The CI gitleaks workflow (.github/workflows/gitleaks.yml) already runs `gitleaks detect --source=.` and gitleaks auto-loads .gitleaks.toml from the source directory per the documented config precedence — no workflow edit required. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apply selective version resolutions for transitive deps where the bump is semver-compatible AND only one major exists in the tree. Skips multi-major cases (picomatch 2.x+4.x, minimatch 3.x+5.x+9.x+ 10.x, glob 7.x+11.x), axios (needs graph-cli upstream), and lodash (advisory affects all of 4.x, no fix without major migration). Resolutions added (root package.json): immutable: 5.1.4 -> ^5.1.5 (advisory 1117068) cross-spawn: 7.0.3 + 7.0.6 -> ^7.0.6 (advisory 1104664) semver: 7.3.5 + 7.7.x -> ^7.5.2 (advisory 1112921) Effect on root yarn.lock: dedups cross-spawn (-2 entries), bumps immutable (1 patch) and semver 7.3.5 (-> 7.7.4 via existing range). Net -50 lines in yarn.lock. Allowlist trimmed from 23 -> 20 entries. Audit script's drift detector flagged the now-cleared advisories as warnings before trim, then exited clean after. Verification: - Root: yarn install --frozen-lockfile clean; yarn audit:prod OK (20 allowlisted, no unlisted high/critical). - All 13 paths: yarn install --frozen-lockfile "Already up-to-date" (subgraph lockfiles untouched — root resolutions don't propagate). - Smoke test: predict-omen (19/19 tests pass), babydegen-optimism (10/10 tests pass) — same counts as PR2's verification. Out of scope (left in allowlist with 90-day review): - 5x axios advisories (need graph-cli upstream migration to axios 1.x) - 3x minimatch (multi-major in tree — risky to force one) - 3x undici, 1x picomatch, 1x lodash, 1x glob - Total: 20 remaining entries, all reviewed 2026-08-05 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fc2ae9a to
428aa5b
Compare
Tanya-atatakai
left a comment
There was a problem hiding this comment.
LGTM. Clean, conservative supply-chain cleanup.
Verified:
- Allowlist now at 20 entries (was 23); the 3 removed GHSAs map 1:1 to the 3 added resolutions.
- Resolutions take effect in yarn.lock: immutable→5.1.5, cross-spawn deduped to 7.0.6, semver consolidated to 7.7.4. Stale transitives (lru-cache@^6, yallist@^4) correctly pruned.
- Caret floors are fix-version minima, not arbitrary picks.
- Multi-major guardrail captured inline via the
//comment in package.json — exactly where a future contributor would be tempted to add picomatch/minimatch/glob. - Rollback is a single revert; subgraph lockfiles untouched by design.
Risk: low. Dep-only, scope is well-defended, CI drift detector already proved itself by flagging the stale entries.
…e.jsons Addresses concerns #1 and #3 from @atepem's review on PR #122. #1: Subgraph yarn.locks shipped vulnerable versions The supply-chain audit gate covers root only (".github/workflows/ supply-chain.yml: 'Dependency audit (root tree)'"). All 12 subgraph yarn.locks still contained the same 3 vulnerable versions that the root resolutions cleared: immutable@5.1.4 (advisory 1117068) cross-spawn@7.0.3 (advisory 1104664) semver@7.3.5 (advisory 1112921) Mirrored the root resolutions block into all 12 subgraph package.jsons with a short pointer back to root for the rationale, then ran 'yarn install' in each subgraph to refresh its yarn.lock. After-state across all 12 subgraphs: immutable 5.1.4 -> 5.1.5 cross-spawn 7.0.3 -> 7.0.6 semver 7.3.5 -> 7.7.4 (forced 7.5.2 floor pulls latest minor) #3: Allowlist entries now cite the multi-major constraint picomatch / minimatch / glob entries previously cited only the graph-cli ceiling. Appended the multi-major reasoning so a future reviewer trying to clear those entries via 'yarn resolutions' sees why the same fix that worked for immutable/cross-spawn/semver does not apply (forcing one major across consumers expecting another breaks installs). Drive-by fix: npm advisory database rotated 1113274 -> 1117857 for the same axios CVE (GHSA-43fc-jf86-j433). Root audit:prod was failing with "stale entry" on 1113274 + "unlisted" on 1117857. Replaced the id in place; reason / dates / GHSA preserved. Verification: - All 12 subgraphs: 'yarn install --frozen-lockfile' passes (12/12). - End-to-end smoke on 3 patterns: legacy-mech-fees (single-network) codegen + build + 15/15 tests predict-omen (nested) codegen + build + 19/19 tests predict-polymarket (nested, dep-heavy) codegen + build + 96/96 tests Total: 130/130 tests green on the new resolutions. - Root 'yarn audit:prod' clean (20 allowlisted, 0 unlisted, exit 0). - Root yarn.lock unchanged; only subgraph trees and the allowlist moved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks @atepem — solid review, addressed all three points. New commit: Concern #1 — subgraph yarn.locks shipped vulnerable versions ✅ FixedConfirmed your point: all 12 subgraph yarn.locks had Picked option A (propagate). Mirrored the root
Verified with full local sequence on three CI patterns:
Plus Concern #2 —
|
rajat2502
left a comment
There was a problem hiding this comment.
LGTM. Mechanism is sound, scope is well-defended, and @atepem's three concerns (subgraph propagation, "//" key safety, multi-major rationale on remaining entries) are all addressed in e7f8b62.
Verified:
- 1:1 pairing between resolutions added and allowlist entries removed.
- Caret floors pinned at the documented fix version (
^7.5.2/^7.0.6/^5.1.5), letting the lockfile pick fresher minors freely. - Subgraph mirrors close the gate-vs-reality gap — the audit workflow only covers root, but the deploy surface (12 subgraph trees) now ships the patched versions too.
- Smoke tests across single-network / nested / dep-heavy patterns (legacy-mech-fees, predict-omen, predict-polymarket = 130/130) cover the riskiest bump (semver 7.3.5 → 7.7.4).
- axios advisory id rotation (1113274 → 1117857) preserves the GHSA — same CVE under a renumbered npm record.
Non-blocking follow-ups for whoever picks up #5:
- Add a CI check that diffs root vs. subgraph
resolutionsso the next root-level addition can't silently skip the 12 mirrors. - Consider factoring the repeated "multi-major-blocked" rationale into the allowlist schema instead of free-text duplication across 11 entries.
…date-3 # Conflicts: # .github/CODEOWNERS # .github/workflows/deploy-subgraph.yaml # .github/workflows/test.yaml # CLAUDE.md # subgraphs/babydegen/babydegen-optimism/yarn.lock # subgraphs/predict/predict-omen/yarn.lock # subgraphs/tokenomics-eth/yarn.lock
…ph-studio into mohan/supply-chain-update-3
…n workflow The merge-cascade commit `b810944` bumped `.nvmrc` from 22.18.0 to 24 to align with main's Node 24 preference (Tanya's PR #119 review). The root package.json's engines.node field was missed in that merge — left at "22.x" while .nvmrc said 24. `yarn install` enforces engines.node strictly. On CI: error autonolas-subgraph-studio@: The engine "node" is incompatible with this module. Expected version "22.x". Got "24.14.1" error Found incompatible module. This crashed `yarn install --frozen-lockfile` as the first step in both the `Dependency audit (root tree)` and `Install-hook audit` jobs in supply-chain.yml — surfaced as 2 CI failures on the b810944 push. Locally re-verified on Node 24.4.1: - yarn install --frozen-lockfile: clean - yarn audit:prod: OK (23 allowlisted, no unlisted) - yarn audit:install-hooks: OK (0 allowlisted) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…date-4 # Conflicts: # .supply-chain/audit-allowlist.json
Summary
Follow-up to #121: clear 3 of the 23 audit allowlist entries via yarn
resolutions. Conservative scope — only resolutions where I'm 100% confident no consumer breaks. Stacked on #121.Changes
Single resolutions block added to root
package.json:Root
yarn.lockregenerated. 3 entries removed from.supply-chain/audit-allowlist.json.Net diff: 3 files, +12 / −71 lines.
Why these three (and not others)
immutablecross-spawnsemverpicomatchminimatchglobaxios(5 advisories!)lodashundici(3 advisories)The skipped ones are tracked for the August 2026 quarterly review or for the eventual graph-cli upstream bumps.
Verification
Root (where the resolution is applied)
yarn install --frozen-lockfileafter editimmutable: 5.1.5,cross-spawn: 7.0.6(deduped),semver: 7.7.4(forced 7.3.5 forward)yarn audit:prodAll 13 paths still deterministic
Subgraph lockfiles are unaffected — root resolutions don't propagate, by design.
Subgraph smoke tests (representative coverage)
Why not also fix the multi-major cases
Yarn 1.x
resolutionsare package-name-level — they pin ALL instances of a package to one version. With multi-major packages like picomatch (2.x callers + 4.x callers) or minimatch (4 majors), forcing one version would either:Yarn 1.x's selective resolution syntax (
some-parent/picomatch) requires knowing every parent in advance and tracking new ones over time — high maintenance cost for marginal advisory clearance. Better to wait for upstream to refresh those transitives.Test plan
yarn install --frozen-lockfileclean.Rollback
Revert is a single commit. Removes the resolutions block, regenerates yarn.lock, restores 3 allowlist entries. Zero side effects in subgraphs (their lockfiles never changed).
Stacked on
Base =
mohan/supply-chain-update-3. Once #121 merges, this PR auto-rebases tomain.