chore(deps): clear every remaining SDK-side advisory via resolutions - #429
Conversation
Takes the repo from 41 open advisories (11 high) to 28 (6 high). More usefully: advisories reachable from `packages/*` go from 8 to **zero**. Everything still open is inside a `demo/*` app, which no CI job builds or tests. These were previously written off as needing the parent tool replaced. That was wrong - the patched versions exist, they just fall outside the range the parent declares, which is exactly what `resolutions` is for. This repo already used it 14 times; this adds 7 more. Four of them had no upstream fix at all, and are gone because the thing that pulled them is gone: - `jsdoc` ^4.0.5 - jsdoc 4 dropped `taffydb` (the only high in the SDK's own tree) and brings `markdown-it` 14 / `linkify-it` 5 with it - `vue-docgen-api` ^4.79.2 - drops `vue-template-compiler` (Vue 2, EOL, no fix will ever ship) - `browserify` + `watchify` removed from packages/js-sdk - no script in the repo references either, and they were the only path to `elliptic` (no upstream fix) and `bn.js` The rest are straightforward forced bumps: `serialize-javascript` >=7.0.5, `diff` >=8.0.3, `pug` / `pug-code-gen` >=3.0.3, `underscore` >=1.13.8. Deliberately no `feat`/`fix` prefix - this is tooling only and must not cut a release. No published package changes: `peerDependencies` are byte-identical to `main` in all 11 packages, and no `dependencies` move. Verified at this commit: - `yarn install --immutable` - passes - `yarn build` at the repo root - 50 bundles, exit 0 - `yarn lint` in packages/js-sdk - clean - 546 mocha tests across 10 packages - passing - 47 browser tests - passing Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Independent code review via The load-bearing check was whether anything left the runtime closure of a published package. It did not: all 13 One methodology note worth recording: seeding the dependency walk from the lockfile workspace entry gives a false result, because Yarn Berry merges The title's word "SDK-side" is load-bearing and accurate: 19 advisories remain vulnerable at HEAD, and all 19 are reachable only from Review — convertcom/javascript-sdk PR #429
What I verified cleanV1. No runtime dependency of any published package changed — verified exhaustivelyThe single highest-stakes question. Method: read each workspace's real
Result — the entire third-party runtime surface of all 13 published packages is one package:
V2.
|
| Package | Vuln version at HEAD | Reachable from |
|---|---|---|
undici |
7.28.0 | demo/cloudflare-workers |
react-router, react-router-dom |
6.30.4 | demo/remixjs-* |
esbuild |
0.17.6, 0.21.5 | demo/remixjs-* |
estree-util-value-to-estree |
1.3.0 | demo/remixjs-* |
postcss |
7.0.39 | demo/reactjs |
svgo |
1.3.2 | demo/reactjs |
webpack-dev-server |
4.15.2 | demo/reactjs |
Zero still-vulnerable package is reachable from any packages/* workspace. The scoping word
"SDK-side" in the title is doing real work and is correct.
V4. All 7 resolutions are honored; none is a dead no-op entry
| Resolution | Base descriptors | HEAD resolved | Satisfies |
|---|---|---|---|
jsdoc: ^4.0.5 |
^3.6.2 |
4.0.5 | yes |
vue-docgen-api: ^4.79.2 |
^3.26.0 |
4.79.2 | yes |
serialize-javascript: >=7.0.5 |
^4.0.0, ^6.0.0/6.0.1/6.0.2 |
7.0.7 | yes |
diff: >=8.0.3 |
^4.0.1, ^5.0.0, ^7.0.0 |
9.0.0 | yes |
pug: >=3.0.3 |
^2.0.3, ^3.0.4 |
3.0.4 | yes |
pug-code-gen: >=3.0.3 |
^2.0.2, ^3.0.4 |
3.0.4 | yes |
underscore: >=1.13.8 |
1.13.6, ^1.13.2/~1.13.2 |
1.13.8 | yes |
V5. Every forced major bump traced to its consumer and cleared
resolutions are blunt — each one overrides a declared range. I enumerated every consumer at base
and checked each SDK-side one:
| Consumer (declared range) | Forced to | SDK-side? | Verdict |
|---|---|---|---|
mocha@11.8.0 (diff@^7.0.0) |
9.0.0 | yes (test:mocha) |
safe — see below |
mocha@11.8.0 (serialize-javascript@^6.0.2) |
7.0.7 | yes | parallel-mode only, not used |
rollup-plugin-jsdoc@0.1.2 (jsdoc@^3.6.2) |
4.0.5 | yes (yarn build) |
exercised by green CI |
better-docs@2.7.3 (vue-docgen-api@^3.26.0) |
4.79.2 | yes (jsdoc template) | zero exposure — see below |
ts-node@10.9.2 (diff@^4.0.1) |
9.0.0 | yes | diff is a lazy require inside dist/repl.js only; tests use -r ts-node/register, never the REPL |
tslint@6.1.3 (diff@^4.0.1) |
9.0.0 | yes (devDep) | lint script is eslint src; tslint is never invoked |
jsonpath@1.3.0 (underscore@1.13.6 exact) |
1.13.8 | no | patch bump |
uvu@0.5.6, rollup-plugin-terser@7.0.2, css-minimizer-webpack-plugin@3.4.1 |
— | no | demo-side |
mocha + diff@9 — the one that needed real proof. mocha/lib/reporters/base.js:16 does
var diff = require('diff') and line 518 calls diff.createPatch('string', actual, expected).
That is the failure-diff path — it only executes when a test fails, so a green CI run does not
exercise it. Verified directly against the published artifact instead:
curl https://registry.npmjs.org/diff/-/diff-9.0.0.tgz | tar xz
node -e "const d=require('./package/libcjs/index.js');
console.log(typeof d.createPatch);
console.log(d.createPatch('string','foo\nbar\n','foo\nbaz\n'))"
-> function
-> Index: string / --- string / +++ string / @@ -1,2 +1,2 @@ / foo / -bar / +baz
diff@9.0.0 still ships CJS (main: ./libcjs/index.js) and exports createPatch with the same
3-arg signature. Mocha's failure reporter is safe.
better-docs + vue-docgen-api@4 — zero functional exposure. vue-docgen-api is consumed only
by node_modules/better-docs/component.js. packages/js-sdk/jsdoc.config.json loads only
better-docs/typescript and better-docs/category as plugins — not component — and the repo
contains 0 .vue files. That resolution exists purely to evict vue-template-compiler
(GHSA-g3ch-rx76-35fx) from the tree; no code path changes.
V6. Lockfile is internally consistent
- Dangling descriptors: 0. Every
dependenciesedge in all 2353 entries resolves. - Semver integrity: all 3021
npm:descriptors checked withsemver.satisfies— 0 entries
resolve outside their own declared range. (One apparent hit,node-gyp@npm:latest-> 13.0.1, is a
dist-tag not a range, and is present identically at base:base.lock:18892,head.lock:18110.) - Resolution sources: 2326
npm:, 21workspace:, 6patch:. All 6 patches are Yarn builtin
compat patches (#optional!builtin<compat/fsevents|resolve|typescript>), not custom patch files.
Nogit:,http:,file:, orportal:sources — clean for a published SDK. - Metadata
version: 8, cacheKey: 10c0;packageManager: yarn@4.10.3.
V7. CI has an immutable-install gate, and it passed on this exact sha
.github/workflows/qa.yml runs yarn install --immutable, then in packages/js-sdk:
yarn lint && yarn build && yarn test:mocha && yarn test:browser.
All check runs are bound to head_sha 5cb979758460c9c23665e0e6ecea9dfc9cf7a107 (verified via
/commits/<sha>/check-runs), and pass-qa (22) = success. The immutable install succeeding at
this sha is direct proof the lockfile matches the manifests with no drift — stronger evidence than a
local install would give here (see Coverage gaps). publish-package.yml and pages.yml also use
yarn install --immutable.
Blocking findings
None.
Non-blocking observations
N1. Five of the seven new resolutions have an unbounded upper bound
serialize-javascript: >=7.0.5, diff: >=8.0.3, pug: >=3.0.3, pug-code-gen: >=3.0.3,
underscore: >=1.13.8 accept any future major. The lockfile pins exact versions and CI is
--immutable, so nothing floats today — but the next deliberate re-resolution can jump a major of
dev tooling with no range guard. The two caret entries (jsdoc: ^4.0.5, vue-docgen-api: ^4.79.2)
are the safer form.
To be fair to the author: this mixed style is pre-existing, not introduced here — the 14 prior
resolutions are 13x >= and 1x caret (path-to-regexp: ^0.1.12). So the caret/>= inconsistency
flagged in the brief is consistent with existing repo practice rather than an oversight in this PR.
Worth a follow-up to settle on one form (>=X <Y+1 would keep the security floor and add a ceiling).
N2. pug / pug-code-gen resolutions are defensive no-ops at present
The pug advisories came from pug@2.0.4, pulled in by vue-docgen-api@3.26.0 (pug@^2.0.3).
Bumping vue-docgen-api to 4.79.2 removes that edge entirely. The only remaining pug consumer is
demo/nodejs (pug@^3.0.4), which already resolves to 3.0.4 — satisfying >=3.0.3 with or without
the resolution. Harmless as a floor; just note they are belt-and-braces, not the active fix.
N3. resolutions do not protect published consumers — fine here, worth knowing
Yarn resolutions in the root (private: true) manifest apply only to this repo's install tree;
they are not published. Anyone npm installing @convertcom/js-sdk gets none of them. That is
harmless in this case precisely because V1 holds — no resolved package is in any published
package's runtime closure. It does mean these entries fix CI/dev-tree advisories only.
N4. The "SDK-side" safety argument leans on demos never being published
demo/nodejs (@convertcom/js-sdk-demo-nodejs) and demo/reactjs (@convertcom/js-sdk-demo-react)
omit private: true. They are not publishable in practice — publish-package.yml publishes only
explicit packages/* directories gated on js-sdk-*-v tags, and release-please-config.json lists
only packages/*. Pre-existing and untouched by this PR; adding "private": true to both would make
the SDK-vs-demo boundary that this PR's scoping relies on structural rather than incidental.
N5. SonarCloud check is attributed to PR #426
gh pr checks 429 reports the SonarCloud check at
https://sonarcloud.io/dashboard?id=convertcom_javascript-sdk&pullRequest=426, and the workflow-run
list for this sha contains both a PR #426 and a PR #429 dynamic run. The check is bound to the
correct head_sha, so the code analyzed is this code; only the PR-number attribution looks off.
Cosmetic, but if SonarCloud decorations land on the wrong PR it is worth a glance.
Coverage gaps
- No local install performed.
corepackis not installed in this environment
(which corepack-> not found) and the global yarn is 4.5.3 vs the repo's pinned
packageManager: yarn@4.10.3. Per the brief I did not force it — running 4.5.3 against a
4.10.3-written lockfile risks rewriting it. The greenyarn install --immutablein CI at this
exact sha covers this question better than a mismatched local install would. - Docs content is unverified.
yarn buildruns jsdoc only for the main package
(generate-rollup-config.mjs:217isMainPackage), andpages.ymlcopies
packages/js-sdk/docstogh-pageson push tomain. A green build proves jsdoc 4.0.5 +
better-docs ran; it does not prove the generated HTML is equivalent to what jsdoc 3.6.11
produced. Recommend eyeballing the gh-pages output after merge — this is the one user-visible
surface the major bumps touch. test:browser/ Playwright ran in CI; I did not re-run it locally.- Dependabot alert state is a snapshot of the default branch taken during this review
(41 open). Alert closure after merge is inferred from lockfile versions, not observed.
Verdict
APPROVE — 0 blocking findings.
The two claims that carried real risk both hold under direct verification: no published package's
runtime dependency closure changes (it is murmurhash@2.0.1 and nothing else, identical at both
revisions), and browserify/watchify have zero references anywhere in the tracked tree. The
advisory bookkeeping in the title is precise — all 19 surviving advisories are demo-only. The one
genuinely non-obvious hazard, mocha's failure-only diff.createPatch path being force-bumped two
majors, was checked against the published diff@9.0.0 artifact rather than assumed safe from green CI.
JosephSamirL
left a comment
There was a problem hiding this comment.
Approved via /convert:approve. An independent code review ran through /convert:review, and this issues the B-G4 human marker at 5cb9797.



Follow-up to #427. Takes the repo from 41 open advisories (11 high) to 28 (6 high) — and more
usefully, advisories reachable from
packages/*go from 8 to zero. Everything still open isinside a
demo/*app, which no CI job builds or tests.Correcting the previous PR
#427 said these remaining advisories "sit behind a parent already at its latest published version
— these need the tool replaced, not upgraded". That was wrong, and worth stating plainly because
it would have closed off the cheap fix.
Checking all 42 alerts: none can be fixed by re-resolution (#427 already harvested those), but 38
of 42 do have a patched version published upstream. It simply falls outside the range the
parent declares — which is exactly what
resolutionsis for. This repo already used thatmechanism 14 times (
tar,nth-check,braces,path-to-regexp, …). This adds 7 more.What changed
Seven
resolutionsentries, and two dead devDependencies deleted. No published package moves:peerDependenciesare byte-identical tomainin all 11 packages, and nodependencieschange.Four of the advisories had no upstream fix at all. They are gone because the thing that pulled
them is gone, not because they were patched:
jsdoc→^4.0.5taffydb— the only high in the SDK's own tree — and bringsmarkdown-it14 /linkify-it5 with itvue-docgen-api→^4.79.2vue-template-compiler(Vue 2, EOL, no fix will ever ship)browserify+watchifyelliptic(no upstream fix) andbn.jsThe rest are ordinary forced bumps:
serialize-javascript>=7.0.5,diff>=8.0.3,pug/pug-code-gen>=3.0.3,underscore>=1.13.8.Verification at
5cb9797yarn install --immutable— passesyarn buildat the repo root — 50 bundles, exit 0yarn lintinpackages/js-sdk— cleanyarn test:mochaacross all 10 test packages — 546 passing, 0 failingyarn test:browserinpackages/js-sdk— 47 passedThe 28 that remain — a separate decision
All demo-only:
react-scripts(webpack-dev-server, postcss, svgo, uuid, @tootallnate/once),Remix (react-router, turbo-stream, vite, esbuild, estree-util-value-to-estree),
wrangler(undici). Three options, none of them "replace the tool":
react-router6→7 underRemix and
webpack-dev-server4→5 underreact-scriptswill very likely break those apps, andsince no CI job builds
demo/, nothing would catch it until someone runs a demo.demo/*from the rootworkspaces. Their trees leave the lockfile entirely and all 28disappear with nothing forced; the demos then install standalone and resolve
@convertcom/js-sdkfrom npm — arguably what a demo should demonstrate. Not measured — thisnumber is a projection.
Two pre-existing issues, still not fixed here
Repo-root
yarn lintis red inpackages/types(src/config/index.ts, generatedsrc/config/types.gen.ts). Pre-existing onmain, untouched here, andpass-qaonly lintspackages/js-sdkso CI has never exercised it.yarn buildleaves a dirty tree.generate-rollup-config.mjsrewrites each package's sourcepackage.json, pinningpeerDependenciesto the current sibling workspace versions — not just thegenerated
lib/package.json. That churn was stripped before committing here; it bit #427 twice.🤖 Generated with Claude Code