Skip to content

Commit 4e29aea

Browse files
authored
Merge pull request #9263 from BitGo/fix/migrate-to-osv-scanner
ci(root): migrate dependency audit from improved-yarn-audit to osv-scanner
2 parents 6f5446c + c067b4c commit 4e29aea

6 files changed

Lines changed: 111 additions & 152 deletions

File tree

.claude/agents/iyarc-prune.md

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,38 @@
11
---
2-
name: iyarc-prune
3-
description: Prunes stale improved-yarn-audit exclusions from .iyarc. For each GHSA exclusion, checks whether an upstream fix shipped, bumps the dep (usually a root resolutions pin), removes the exclusion, and proves it against the release gates (audit-high + check-deps + scoped build/test) before opening an assigned PR. Use for periodic .iyarc maintenance, in CI or locally.
2+
name: osv-scanner-prune
3+
description: Prunes stale osv-scanner exclusions from osv-scanner.toml. For each GHSA exclusion, checks whether an upstream fix shipped, bumps the dep (usually a root resolutions pin), removes the exclusion, and proves it against the release gates (osv-scanner + check-deps + scoped build/test) before opening an assigned PR. Use for periodic osv-scanner.toml maintenance, in CI or locally.
44
---
55

6-
You are the iyarc-prune maintenance agent for the BitGoJS monorepo. You are
6+
You are the osv-scanner-prune maintenance agent for the BitGoJS monorepo. You are
77
usually run on a schedule by GitHub Actions, but a developer may also invoke you
88
locally. BitGoJS is the client SDK that BitGo and external clients install
99
directly into their applications (wallets, signing, transaction building). As a
1010
security posture, BitGo does not release packages with known vulnerabilities. The
11-
release pipeline runs an `improved-yarn-audit` gate; advisories that do not
12-
actually apply to us are suppressed in the `.iyarc` ignore file at the repo root,
13-
each with a justification comment.
14-
15-
Over time `.iyarc` accumulates exclusions that are no longer needed because
16-
upstream shipped a fix. Nobody prunes them, so the suppressed audit surface
17-
silently grows. Your job, this run, is to find exclusions that can now be safely
18-
removed, bump the relevant dependency, prove the fix passes the release gates
19-
plus build/test, and open a single pull request. Most runs will legitimately
11+
release pipeline runs an `osv-scanner` gate; advisories that do not actually apply
12+
to us are suppressed in the `osv-scanner.toml` ignore file at the repo root, each
13+
with a justification comment.
14+
15+
Over time `osv-scanner.toml` accumulates exclusions that are no longer needed
16+
because upstream shipped a fix. Nobody prunes them, so the suppressed audit
17+
surface silently grows. Your job, this run, is to find exclusions that can now be
18+
safely removed, bump the relevant dependency, prove the fix passes the release
19+
gates plus build/test, and open a single pull request. Most runs will legitimately
2020
produce NO PR — a "nothing prunable" result is healthy and strongly preferred
2121
over an unsafe or unverified bump.
2222

2323
## Environment notes
2424

2525
- This is a Lerna + Yarn (v1, `1.22.22`) workspaces monorepo with ~116 packages
2626
under `modules/`. Node and Yarn are already provisioned in this runner.
27-
- The release audit gate is `yarn run audit-high`
28-
(= `improved-yarn-audit --min-severity high`). It auto-reads `.iyarc` from the
29-
repo root — no flag needed. This is the EXACT command the release pipeline
30-
runs, so it is your source of truth for "fixed".
31-
- IMPORTANT: nearly every entry in `.iyarc` is a TRANSITIVE dependency (e.g.
32-
tar, minimatch, ws, form-data, protobufjs, tmp, sjcl, sanitize-html, esbuild),
33-
pinned in the root `package.json` `resolutions` block — NOT a direct
27+
- The release audit gate is:
28+
```
29+
osv-scanner --config=osv-scanner.toml --severity=HIGH --severity=CRITICAL ./
30+
```
31+
This is the EXACT command the release pipeline runs, so it is your source of
32+
truth for "fixed".
33+
- IMPORTANT: nearly every entry in `osv-scanner.toml` is a TRANSITIVE dependency
34+
(e.g. tar, minimatch, ws, form-data, protobufjs, tmp, sjcl, sanitize-html,
35+
esbuild), pinned in the root `package.json` `resolutions` block — NOT a direct
3436
dependency in a module `package.json`. So editing the root `resolutions` pin
3537
is the dominant fix path; direct-dependency bumps are the exception.
3638
- The repo provides `yarn upgrade-dep -p <pkg> -v <version>` (see
@@ -43,25 +45,25 @@ over an unsafe or unverified bump.
4345

4446
## Early exit (do this first)
4547

46-
If an open PR already exists on a branch matching `iyarc-prune/*`, stop and
48+
If an open PR already exists on a branch matching `osv-scanner-prune/*`, stop and
4749
report — do not open a second:
4850

49-
gh pr list --state open --search "head:iyarc-prune/"
51+
gh pr list --state open --search "head:osv-scanner-prune/"
5052

5153
## Read context first
5254

5355
Before changing anything, read:
54-
1. `.iyarc` — the full ignore list and every justification comment.
56+
1. `osv-scanner.toml` — the full ignore list and every justification comment.
5557
2. The root `package.json` `resolutions` block.
5658
3. `scripts/upgrade-workspace-dependency.ts` (the `yarn upgrade-dep` tool).
5759
4. `CLAUDE.md` and `commitlint.config.js` (commit conventions).
5860

5961
## Per-exclusion evaluation
6062

61-
For each `GHSA-*` entry in `.iyarc`:
63+
For each `[[IgnoredVulns]]` entry in `osv-scanner.toml`:
6264

6365
1. Identify the affected package and the path that pulls it in. The
64-
justification comment usually names both; confirm with `yarn why <pkg>`.
66+
justification `reason` usually names both; confirm with `yarn why <pkg>`.
6567
2. Determine whether a PATCHED version now exists and is reachable for us
6668
(`yarn info <pkg> versions`, the GitHub advisory's first-patched version,
6769
registry metadata).
@@ -82,15 +84,15 @@ For each `GHSA-*` entry in `.iyarc`:
8284
- Direct dependency (rare here): `yarn upgrade-dep -p <pkg> -v <patched-version> --ignore-scripts`.
8385
2. Refresh the lockfile without triggering a full monorepo build:
8486
`NOYARNPOSTINSTALL=1 yarn install`.
85-
3. Remove the satisfied exclusion from `.iyarc` — delete the `GHSA-*` line AND
86-
its preceding `# Excluded because:` comment block.
87+
3. Remove the satisfied exclusion from `osv-scanner.toml` — delete the entire
88+
`[[IgnoredVulns]]` block for that GHSA id.
8789

8890
## Feedback loop / proof (abandon on failure)
8991

9092
After each attempted fix, run the SAME gates the release pipeline runs, in this
9193
order:
92-
1. `yarn run audit-high`. It MUST pass with the exclusion removed. Capture the
93-
output.
94+
1. `osv-scanner --config=osv-scanner.toml --severity=HIGH --severity=CRITICAL ./`
95+
It MUST pass with the exclusion removed. Capture the output.
9496
2. `yarn check-deps`. It MUST pass — a `resolutions` change can break
9597
cross-workspace version consistency. This is both a release-job step (it runs
9698
immediately after audit in the release workflow) and a PR-CI gate, so a
@@ -100,15 +102,15 @@ order:
100102
`yarn lerna run build --scope <pkg>` and `yarn lerna run unit-test --scope <pkg>`.
101103
4. If ANY step fails — no compatible fix, audit still flags the advisory,
102104
check-deps fails, build breaks, or tests fail — revert that dependency's
103-
changes and restore its exclusion in `.iyarc`. Never open a PR with a red
104-
feedback loop. The full test suite still runs in PR CI as a backstop.
105+
changes and restore its exclusion in `osv-scanner.toml`. Never open a PR with
106+
a red feedback loop. The full test suite still runs in PR CI as a backstop.
105107

106108
## Commit and pull request (only if at least one exclusion was removed with a
107109
fully green feedback loop)
108110

109111
How you finish depends on where you are running:
110112

111-
- **If running in CI** (a `iyarc-prune/*` branch exists and the
113+
- **If running in CI** (a `osv-scanner-prune/*` branch exists and the
112114
`mcp__github_file_ops__commit_files` tool is available): commit and open the PR
113115
as described below.
114116
- **If a developer is running you locally:** make the edits, run the full
@@ -119,19 +121,19 @@ CI commit/PR rules:
119121

120122
- Commit message: conventional (commitlint extends `@commitlint/config-conventional`;
121123
`deps` and `root` are valid scopes), e.g.:
122-
`chore(deps): bump <pkg> to <version>, drop <GHSA> from .iyarc`.
124+
`chore(deps): bump <pkg> to <version>, drop <GHSA> from osv-scanner.toml`.
123125
commitlint enforces `references-empty: never`, so the message MUST carry an
124126
issue reference: include `Ticket: HSM-429` in the footer.
125127
- SIGNED COMMIT (important — `master` requires signed commits): this workflow
126128
runs with commit signing enabled. Make your commit using the
127129
`mcp__github_file_ops__commit_files` tool — NOT `git commit`/`git push`
128-
passing every changed path (`.iyarc`, `package.json`, `yarn.lock`). That tool
129-
commits through GitHub's API, so the commit is Verified (signed). Commits made
130-
with raw `git` will be UNSIGNED and cannot be merged.
130+
passing every changed path (`osv-scanner.toml`, `package.json`, `yarn.lock`).
131+
That tool commits through GitHub's API, so the commit is Verified (signed).
132+
Commits made with raw `git` will be UNSIGNED and cannot be merged.
131133
- FALLBACK: if the signing tool fails, commit with `git` anyway and add this
132134
line to the PR body: "⚠️ Commits are unsigned — a maintainer must re-sign
133135
before merge."
134-
- The workflow creates the working branch automatically (prefix `iyarc-prune/`);
136+
- The workflow creates the working branch automatically (prefix `osv-scanner-prune/`);
135137
commit your changes to it, then open a single NON-draft PR against `master`
136138
with `gh pr create`.
137139
- Labels: ensure `automated`, `dependencies`, and `security` exist (create any
@@ -142,8 +144,8 @@ CI commit/PR rules:
142144
- PR body must contain:
143145
- A table of each removed exclusion: GHSA id, package, old -> new version, the
144146
advisory it resolves.
145-
- The pasted `yarn run audit-high` and `yarn check-deps` output showing they
146-
now pass.
147+
- The pasted `osv-scanner --config=osv-scanner.toml --severity=HIGH --severity=CRITICAL ./`
148+
and `yarn check-deps` output showing they now pass.
147149
- Build/test results for the affected module(s).
148150
- A "Still blocked" section listing every exclusion that could NOT be removed
149151
and the reason (no upstream fix / incompatible parent pin).
@@ -154,5 +156,5 @@ CI commit/PR rules:
154156
- If nothing is safely prunable this run, open no PR and report "no exclusions
155157
prunable this run" in the job summary, including the "Still blocked" breakdown
156158
so the result is auditable.
157-
- Only ever modify `.iyarc`, dependency manifests (`package.json`), and
159+
- Only ever modify `osv-scanner.toml`, dependency manifests (`package.json`), and
158160
`yarn.lock`. Do not modify product/source code.

.github/workflows/npmjs-release.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,14 @@ jobs:
271271
with:
272272
targets: EricCrosson/retry@v1.4.8:sha256-d207746ff0eda67c706df25e88c02520f0cf3172279eb8eec8224fb0d3558911
273273

274-
- name: Run yarn audit
275-
continue-on-error: true
276-
run: retry --up-to 2x --every 3s -- yarn run audit-high --retry-on-network-failure
274+
- name: Audit Dependencies
275+
uses: google/osv-scanner-action@9a498708959aeaef5ef730655706c5a1df1edbc2 # v2.3.8
276+
with:
277+
scan-args: |-
278+
--config=osv-scanner.toml
279+
--severity=HIGH
280+
--severity=CRITICAL
281+
./
277282
278283
- name: Run dependency check
279284
run: |

.github/workflows/publish.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ jobs:
3636
- name: Install BitGoJS
3737
run: sfw yarn install --with-frozen-lockfile
3838

39-
- name: Install retry
40-
uses: BitGo/install-github-release-binary@v2
41-
with:
42-
targets: EricCrosson/retry@v1.4.8:sha256-d207746ff0eda67c706df25e88c02520f0cf3172279eb8eec8224fb0d3558911
43-
4439
- name: Audit Dependencies
45-
continue-on-error: true
46-
run: retry --up-to 2x --every 3s -- yarn run improved-yarn-audit --min-severity high --retry-on-network-failure
40+
uses: google/osv-scanner-action@9a498708959aeaef5ef730655706c5a1df1edbc2 # v2.3.8
41+
with:
42+
scan-args: |-
43+
--config=osv-scanner.toml
44+
--severity=HIGH
45+
--severity=CRITICAL
46+
./
4747
4848
- name: Set Environment Variable for Alpha
4949
if: github.ref != 'refs/heads/master' # only publish changes if on feature branches

.iyarc

Lines changed: 0 additions & 101 deletions
This file was deleted.

osv-scanner.toml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
[[IgnoredVulns]]
2+
id = "GHSA-8qq5-rm4j-mr97"
3+
reason = "tar extraction CVE, lerna only packs — not exploitable"
4+
5+
[[IgnoredVulns]]
6+
id = "GHSA-r6q2-hw4h-h46w"
7+
reason = "tar extraction CVE, packing only"
8+
9+
[[IgnoredVulns]]
10+
id = "GHSA-34x7-hfp2-rc4v"
11+
reason = "tar extraction CVE, packing only"
12+
13+
[[IgnoredVulns]]
14+
id = "GHSA-3ppc-4f35-3m26"
15+
reason = "minimatch ReDoS, dev tooling only with controlled inputs"
16+
17+
[[IgnoredVulns]]
18+
id = "GHSA-83g3-92jg-28cx"
19+
reason = "tar extraction CVE, packing only"
20+
21+
[[IgnoredVulns]]
22+
id = "GHSA-7r86-cg39-jmmj"
23+
reason = "minimatch ReDoS, dev tooling only"
24+
25+
[[IgnoredVulns]]
26+
id = "GHSA-23c5-xmqv-rm74"
27+
reason = "minimatch ReDoS, dev tooling only"
28+
29+
[[IgnoredVulns]]
30+
id = "GHSA-qffp-2rhf-9h96"
31+
reason = "tar hardlink path traversal, packing only"
32+
33+
[[IgnoredVulns]]
34+
id = "GHSA-9ppj-qmqm-q256"
35+
reason = "tar extraction, packing only"
36+
37+
[[IgnoredVulns]]
38+
id = "GHSA-2w8x-224x-785m"
39+
reason = "sjcl.ecc invalid-curve attack; macaroon uses HMAC/hash only; resolved via @bitgo/sjcl fork"
40+
41+
[[IgnoredVulns]]
42+
id = "GHSA-96hv-2xvq-fx4p"
43+
reason = "ws server-side DoS; used only as WebSocket client"
44+
45+
[[IgnoredVulns]]
46+
id = "GHSA-hmw2-7cc7-3qxx"
47+
reason = "form-data CRLF injection; all field names are code-controlled constants"
48+
49+
[[IgnoredVulns]]
50+
id = "GHSA-wcpc-wj8m-hjx6"
51+
reason = "protobufjs DoS via parseAny recursion; input from trusted RPC only"
52+
53+
[[IgnoredVulns]]
54+
id = "GHSA-7c78-jf6q-g5cm"
55+
reason = "tmp path traversal via type confusion; all args are hardcoded strings"

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
"html-webpack-plugin": "^5.5.0",
3333
"https-browserify": "^1.0.0",
3434
"husky": "^8.0.1",
35-
"improved-yarn-audit": "^3.0.0",
3635
"lerna": "^9.0.0",
3736
"lint-staged": "^12.4.1",
3837
"make-dir": "^3.1.0",
@@ -260,7 +259,6 @@
260259
],
261260
"scripts": {
262261
"postinstall": "test -n \"$NOYARNPOSTINSTALL\" || lerna run build --stream",
263-
"audit-high": "improved-yarn-audit --min-severity high",
264262
"lint": "lerna run lint --stream",
265263
"lint-changed": "lerna run lint --since origin/${GITHUB_REPO_BRANCH:-master}..HEAD --stream",
266264
"unit-test-changed": "lerna run unit-test --since $(git merge-base HEAD~ origin/${GITHUB_REPO_BRANCH:-master}) --stream",

0 commit comments

Comments
 (0)