Skip to content

Update dependecies, fix d3-color ReDoS vulnerability - #78

Open
mikima wants to merge 8 commits into
masterfrom
chore/deps-phase1
Open

Update dependecies, fix d3-color ReDoS vulnerability#78
mikima wants to merge 8 commits into
masterfrom
chore/deps-phase1

Conversation

@mikima

@mikima mikima commented Aug 24, 2026

Copy link
Copy Markdown
Member

Dependency modernization for rawgraphs-core: build toolchain (Rollup 1→4, Babel, Jest 30), D3 submodules v1/v2/v3→v7, and a fix for the d3-color ReDoS vulnerability (GHSA-36jr-mh4h-2g58) flagged by npm audit.

No changes to the public API (chart(), legend(), etc. keep the same signatures).

d3-color security fix

Added overrides in package.json forcing d3-color, d3-selection, and d3-transition to their current major versions everywhere in the dependency tree — including inside d3-svg-legend, a transitive dependency that's been unmaintained since 2022 and still declares its own old d3-selection@1.0.2/d3-transition@1.0.3.

Legend rendering bug (found while testing the above)

The d3-selection/d3-transition override above initially broke chart legends (cell.exit(...).transition is not a function). Root cause: Vite's dev-time dependency pre-bundling treats the d3 meta-package (what rawgraphs-charts uses to build chart selections) and the standalone d3-selection/d3-transition sub-packages as separate entries — even pointing at the identical files on disk, it produces two separate bundled copies of the Selection class. legend.js's prototype patch was reaching the wrong copy.

Fixed by importing { selection, transition } from "d3" (the same specifier rawgraphs-charts uses) instead of the standalone sub-packages, so both resolve to the same shared bundle. Verified working in both dev and production builds.

Not included, deliberately

d3-svg-legend itself remains as a dependency — it's abandoned (last published June 2022) and this fix works around it rather than replacing it. Worth a follow-up: RAWGraphs only uses a small slice of its API (legendColor()/legendSize()), so a minimal custom implementation could remove this dependency entirely.

mikima and others added 8 commits August 21, 2026 15:51
CI was still pinned to Node 14.x (EOL since April 2023), so
compatibility issues with modern Node never surfaced until tested
locally. package-lock.json also still reported beta.16 while
package.json had already moved to beta.17.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
npm update against the existing caret ranges, no major bumps. Drops
audit findings from 144 (19 critical) to 101 (3 critical) as a side
effect. Build and full test suite (16 tests) still pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- rollup-plugin-babel (deprecated, incompatible with Rollup 3+) replaced
  with @rollup/plugin-babel; requires the now-mandatory babelHelpers
  option, set to 'bundled' to match prior behavior.
- Rollup's own plugins (@rollup/plugin-commonjs/json/node-resolve)
  bumped to the versions compatible with Rollup 4's peer requirements.
- @babel/core and @babel/preset-env bumped to the latest 7.x (7.29.7).
  Deliberately not moving to Babel 8: it just shipped and
  @rollup/plugin-babel@7.1.0 still pins its peer to @babel/core ^7.0.0.
- rollup.config.js → rollup.config.mjs, and the package.json import
  switched from `import pkg from './package.json'` to
  createRequire(...)('./package.json'): Rollup 4's config loader runs
  as native ESM on current Node, which rejects a bare JSON import
  without an import attribute. createRequire sidesteps the Node
  version-dependent import-attribute syntax entirely.
- Jest 25→30, babel-jest 25→30.

Verified: npm run build (Rollup output), npm test (16/16 passing),
npm run nodebox (babel-node sandbox) all still work.

Vulnerabilities per npm audit: 101 → 83 (3 critical, unchanged from
the Phase 1 commit since this is a devDependency-only tree).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- rollup-plugin-babel (deprecated, incompatible with Rollup 3+) replaced
  with @rollup/plugin-babel; requires the now-mandatory babelHelpers
  option, set to 'bundled' to match prior behavior.
- Rollup's own plugins (@rollup/plugin-commonjs/json/node-resolve)
  bumped to the versions compatible with Rollup 4's peer requirements.
- @babel/core and @babel/preset-env bumped to the latest 7.x (7.29.7).
  Deliberately not moving to Babel 8: it just shipped and
  @rollup/plugin-babel@7.1.0 still pins its peer to @babel/core ^7.0.0.
- The package.json import switched from `import pkg from './package.json'`
  to createRequire(...)('./package.json'): Rollup 4's config loader runs
  as native ESM on current Node, which rejects a bare JSON import
  without an import attribute. createRequire sidesteps the Node
  version-dependent import-attribute syntax entirely.
- Jest 25→30, babel-jest 25→30.

(Previous commit a21fcbb only captured the rollup.config.js→.mjs
rename due to a bad `git add` invocation; this one carries the actual
content changes plus package.json/package-lock.json.)

Verified: npm run build (Rollup output), npm test (16/16 passing),
npm run nodebox (babel-node sandbox) all still work.

Vulnerabilities per npm audit: 101 → 83 (3 critical).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
package.json declared "module": "lib/index.esm.js", but Rollup's
entryFileNames template normalizes the 'esm' format alias to 'es',
so the file has always actually been built as lib/index.es.js — the
declared path never existed. charts uses the same "es.js" convention
in its own package.json, confirming this was the intended name.

Harmless for a normal npm install (bundlers fall back to "main" when
"module" doesn't resolve), but surfaced as a real failure when testing
via `npm link`: found while verifying the local npm-link workflow for
testing unpublished core changes in charts/app, where charts' Rollup
build reported @rawgraphs/rawgraphs-core as an unresolved external
dependency in its UMD output.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Brings core's D3 dependencies in line with what app and charts
already use (both on d3 v7). All bumped packages:
d3-array 2→3, d3-axis 1→3, d3-color 1→3, d3-dsv 1→3, d3-format 1→3,
d3-interpolate 1→3, d3-quadtree 2→3, d3-scale 3→4,
d3-scale-chromatic 1→3, d3-selection 1→3, d3-time-format 2→4.

The APIs core actually uses (group/groups/rollup/rollups, min/max/
extent, scaleDiverging/scaleSequential/scaleOrdinal, quantize/
interpolateRgbBasis, timeParse/timeFormatLocale, formatLocale,
tsvParse, select, quadtree, axisBottom/axisLeft) have been stable
across these majors, so no source changes were needed.

d3-svg-legend was NOT touched: its latest published version (2.25.6)
is already what was installed — the package hasn't been updated at
all, not that we were behind. It keeps its own internal, isolated
copy of an old d3-selection (visible in the rollup circular-dependency
warnings) and works fine duck-typing against v7 scale/format objects,
confirmed by the full test suite passing. No fork needed.

Also removed a redundant duplicate `d3-selection` entry that existed
in devDependencies (unused, already a real dependency) at the old v1
range.

Fixed to make this actually testable: npm test was failing across the
board with "Unexpected token 'export'" because D3 v3+ packages ship
ESM-only (no CJS build), and Jest ignores node_modules by default.
Added transformIgnorePatterns to un-ignore d3-*/internmap. That alone
wasn't enough — Babel's `.babelrc.js` format only applies within its
own package boundary, so files jest was reaching into inside
node_modules/d3-* still weren't transformed. Renamed to
`babel.config.js` (project-wide, applies regardless of which
node_modules package a file lives in), which is also the currently
recommended format going forward.

Verified: npm run build, npm test (16/16 passing), npm run nodebox
all work. Vulnerabilities unchanged (83, 3 critical) — this is a
runtime-dependency change, the remaining findings are all in the
devDependency build-tool tree.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Brings core's D3 dependencies in line with what app and charts
already use (both on d3 v7). All bumped packages:
d3-array 2→3, d3-axis 1→3, d3-color 1→3, d3-dsv 1→3, d3-format 1→3,
d3-interpolate 1→3, d3-quadtree 2→3, d3-scale 3→4,
d3-scale-chromatic 1→3, d3-selection 1→3, d3-time-format 2→4.

The APIs core actually uses (group/groups/rollup/rollups, min/max/
extent, scaleDiverging/scaleSequential/scaleOrdinal, quantize/
interpolateRgbBasis, timeParse/timeFormatLocale, formatLocale,
tsvParse, select, quadtree, axisBottom/axisLeft) have been stable
across these majors, so no source changes were needed.

d3-svg-legend was NOT touched: its latest published version (2.25.6)
is already what was installed — the package hasn't been updated at
all, not that we were behind. It keeps its own internal, isolated
copy of an old d3-selection (visible in the rollup circular-dependency
warnings) and works fine duck-typing against v7 scale/format objects,
confirmed by the full test suite passing. No fork needed.

Also removed a redundant duplicate `d3-selection` entry that existed
in devDependencies (unused, already a real dependency) at the old v1
range.

Also adds the transformIgnorePatterns/babel.config.js fix from the
previous commit's rename that made testing this possible in the first
place (npm test was failing across the board on ESM-only D3 v3+
packages until both pieces were in place).

Verified: npm run build, npm test (16/16 passing), npm run nodebox
all work. Vulnerabilities unchanged (83, 3 critical) — this is a
runtime-dependency change, the remaining findings are all in the
devDependency build-tool tree.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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