Skip to content

[Security] Fix dependency vulnerabilities - #526

Draft
anagperal wants to merge 5 commits into
developmentfrom
fix/dependency-vulnerabilities
Draft

anagperal wants to merge 5 commits into
developmentfrom
fix/dependency-vulnerabilities

Conversation

@anagperal

Copy link
Copy Markdown

📌 References

📝 Implementation

Triaged from the live Dependabot alerts: 128 open on development, 39 packages, all on the root yarn.lock, every one still matching a version in the lockfile.

Four remediation types, in order of preference:

  • Lockfile refresh: the patched version already satisfies the parent's declared range, so the stale yarn.lock entry was deleted and re-resolved. No manifest change.
  • Removal: two devDependencies nothing uses (bundle-phobia-cli, vite-plugin-eslint), and the deprecated @types/classnames stub (classnames ships its own types).
  • Direct dependency bump: lodash (4.17.21 → ^4.18.1) and tsx (4.21.0 → 4.23.15).
  • Resolution: only when the fix is outside the parent's declared range. 7 entries, each documented in the new RESOLUTIONS.md.
Package Installed Advisory Introduced by Remediation Now
axios 1.6.4 13 high, 15 medium, 1 low @eyeseetea/d2-api (exact 1.6.4) Resolution 1.20.0
qs 6.9.7 / 6.11.2 GHSA-4mjr-xmp4-gh2g and 2 more (medium), 1 low @eyeseetea/d2-api (exact 6.9.7), url polyfill Resolution 6.16.0
lodash 4.17.21 GHSA-r5fr-rjxr-66jc (high), 2 medium Direct (exact), d2-api and d2-ui-components (exact) Direct bump and resolution 4.18.1
linkify-it 2.2.0 GHSA-v245-v573-v5vm, GHSA-22p9-wv53-3rq4 (high) d2-ui-components → react-linkify (^2.0.3) Resolution 5.0.2
node-fetch 1.7.3 GHSA-r683-j2x4-v87g (high) d2, d2-ui-components → d2-ui-core (d2; material-ui@0.20 → recompose → fbjs) → isomorphic-fetch (^1.0.1) Resolution 2.7.0
node-gettext 2.1.0 GHSA-g974-hxvm-x689 (high) @dhis2/d2-i18n-extract/generate → i18next-conv@6.1.1 Resolution 3.0.1
postcss 8.4.38 / 8.4.29 2 high, 3 medium styled-components (exact 8.4.38) / vite Resolution / lockfile refresh 8.5.28
lodash.pick 4.4.0 GHSA-p6mc-m468-83gw (high, no fix) vite-plugin-checker@0.6.2 Parent refreshed to 0.6.4, which dropped it gone
got, tmp 9.6.0, 0.0.33 1 medium; 1 high, 1 low bundle-phobia-cli (unused) Removed gone
rollup 2.79.1 / 3.29.2 GHSA-gcx4-mw62-g8wm, GHSA-mw96-cpmx-2vgc (high) vite-plugin-eslint (unused) / vite Removed / lockfile refresh gone / 3.30.0
esbuild 0.27.3 GHSA-g7r4-m6w7-qqqr (low) tsx@4.21.0 (~0.27.0) tsx bump 0.28.2
vite 4.4.9 13 of its 19 alerts Direct (^4.2.0) Lockfile refresh 4.5.14
@babel/traverse, cipher-base, form-data, handlebars, pbkdf2, sha.js, elliptic critical @babel/core, Node polyfills, d2-api/jsdom, @dhis2/d2-i18n-generate Lockfile refresh patched
@adobe/css-tools, @babel/core/runtime/plugin-transform-modules-systemjs, @tootallnate/once, brace-expansion, braces, browserify-sign, browserslist, ejs, flatted, follow-redirects, js-yaml, minimatch, nanoid, path-to-regexp, picomatch, ws high/medium/low Toolchain, polyfills, react-router@5 Lockfile refresh See yarn why
  • Every critical but one is closed. @babel/traverse, cipher-base, elliptic (GHSA-vjh7-7g9h-fjfh), form-data, handlebars, pbkdf2 and sha.js were all stale lockfile entries with the fix inside their parent's range. The one left is vitest, which needs the vite migration.
  • axios, qs and lodash are pinned exactly by @eyeseetea/d2-api (and lodash also by @eyeseetea/d2-ui-components), the same cause every other app in #869f1gfjj carries a resolution for. The app uses d2-api's fetch backend (src/types/d2-api.ts), which uses qs; axios is the backend only for scripts with backend: "xhr". Both backends were driven against a local server (a GET with fields and repeated filter params, a POST /metadata with a body, and api.models.dataSets.get): the requests are byte-identical to the ones sent from development.
  • react-linkify/linkify-it bound to nothing on the first attempt. Yarn Classic installed it successfully and left linkify-it@2.2.0 in place, with no warning; it needed the **/ prefix. Recorded under "Rejected pins" in RESOLUTIONS.md. The pinned version was then checked through react-linkify itself: URLs, www. hosts and e-mail addresses still match, and <Linkify> renders the expected <a href>.
  • node-gettext was verified through the scripts that use it: yarn localize (extract-pot, msgmerge, d2-i18n-generate) produces a byte-identical i18n/en.pot and src/locales/ with 3.0.1 and with 2.1.0.
  • styled-components/postcss replaces a copy that never runs: styled-components@6.1.11 lists postcss as a dependency but nothing in its dist/ loads it. Upgrading styled-components to 6.4.0+ (the first release without postcss) is the preferred fix and was tried: with 6.5.3, tsc fails in IndicatorsDataSet.tsx (styled(Checkbox) no longer passes the event type to onChange), and the new styling library across 19 source files needs checking in a running app. Left as a follow-up ticket; the resolution changes nothing that executes.
  • The vite refresh brings one new advisory into range. GHSA-93m4-6634-74q7 (medium, Windows-only dev server) affects >= 4.5.3, < 5.0.0: 4.4.9 was below it, 4.5.14 is inside it. The same refresh closes 13 vite advisories, including GHSA-c24v-8rfc-w8vw (high). Dependabot will open an alert for it after merge. Fixed only on vite 5.4.21+.
  • In scope beyond Dependabot: yarn audit also reported cross-spawn, get-func-name, diff, ajv, bn.js, micromatch and yaml, each with a fix inside its parent's range. Refreshed too.
  • RESOLUTIONS.md created (did not exist before this PR).
  • One non-dependency change, in its own commit: yarn lint failed on development with a false positive in src/data/entry-form/template.js:481. testing-library/await-async-utils read the wait parameter of a local debounce(func, wait) as Testing Library's deprecated wait(). Renamed to delayMs. Without it, the pre-push hook (yarn prettify && yarn lint && ...) blocks every push. template.js is injected into the custom form as raw text, so the rename changes nothing else; the test suite still passes.
  • Formatting only, in its own commit: template.css, Project.ts, SaveDataSetUseCase.ts and metadata_old_projects_in_cc_deprecated_sqlview.json were left unformatted on development, so the pre-push hook's yarn prettify rewrote them on every push. No behaviour change.

📹 Screenshots/Screen capture

None. No UI change.

🔥 Is there anything the reviewer should know to test it?

Run on Node 18.16.1 (nvm use first) / Yarn 1.22.22. Every check was run on development first, and the results compared.

Check development This branch
yarn install --frozen-lockfile clean clean, same peer-dependency warnings
Lockfile vs. the 128 open Dependabot alerts 128 match 9 match, all listed under "stays open" below
yarn audit 331 (23 critical, 149 high) 26 (1 critical, 6 high), all listed under "stays open" below. Different advisory source than Dependabot, so counts differ
yarn lint 1 error, 4 warnings 0 errors, the same 4 warnings (see the template.js note below)
npx tsc --noEmit clean clean
yarn test 11 files, 123 tests passed 11 files, 123 tests passed
yarn build clean, main chunk 2,483,138 bytes clean, main chunk 2,563,157 bytes (+80 KB from newer releases of bundled packages)
d2-api requests, both backends, local server baseline byte-identical
yarn localize baseline en.pot and src/locales/ byte-identical
tsx scripts (--help on the four package.json scripts) two parse arguments, two fail loading template.vm identical. The template.vm failure is pre-existing: tsx cannot load the ?raw import that only Vite understands

Findings that stay open, recorded in RESOLUTIONS.md:

  • vitest@0.32.4 (GHSA-5xrq-8626-4rwp, critical), vite@4.5.14 (GHSA-fx2h-pf6j-xcff and GHSA-c27g-q93r-2cwf high, 3 medium, 2 low) and esbuild@0.18.20 (GHSA-67mh-4wv8-2f99, medium). vitest@0.32 and vite-plugin-node-stdlib-browser@0.2.1 (its latest release) both cap vite at 4, and every remaining fix is on 5.x or 6.x. One migration closes all of them. The vitest advisory needs the Vitest UI server, and @vitest/ui is not installed.
  • elliptic@6.6.1 (GHSA-848j-6mx2-7j84, low). Every published version is affected. Same accepted finding as dhis2-app-skeleton, metadata-synchronization and user-extended.

✅ Notes to the tester

  • nvm use, yarn install --frozen-lockfile: clean, no new peer-dependency warnings.
  • yarn lint, npx tsc --noEmit, yarn test, yarn build: all clean (lint keeps 4 pre-existing warnings).
  • yarn why axios → 1.20.x, yarn why qs → 6.16.x, yarn why lodash → a single 4.18.x, yarn why linkify-it → 5.0.2.
  • yarn start against a DHIS2 instance: log in, list projects, create and edit a project through every wizard step (setup, indicators, disaggregation, grey fields, sharing, summary) and open its custom data-entry form.

📑 Others

  • Downstream: axios, qs and lodash can be dropped from resolutions once @eyeseetea/d2-api and @eyeseetea/d2-ui-components request patched versions natively (axios >= 1.18.0, qs >= 6.16.0, lodash >= 4.18.1; both already tracked in #869f1gfjj).

Closes 119 of the 128 open Dependabot alerts, every critical except
vitest:

- Lockfile refresh for every fix already inside the parent's range
  (@babel/traverse, cipher-base, elliptic, form-data, handlebars,
  pbkdf2, sha.js and the rest of the toolchain; vite within 4.x).
- Remove unused devDependencies bundle-phobia-cli and vite-plugin-eslint
  (takes got, tmp and rollup@2 with them) and the deprecated
  @types/classnames stub.
- Bump tsx to 4.23.15 (esbuild 0.28) and lodash to ^4.18.0.
- Resolutions where the fix is outside the parent's range: axios, qs and
  lodash (pinned exactly by @eyeseetea/d2-api / d2-ui-components),
  linkify-it, node-fetch, node-gettext and styled-components' postcss.

Every resolution is documented in the new RESOLUTIONS.md, with what it
fixes, how it was verified and when it can be dropped. vitest, vite and
esbuild 0.18 need the vite 6 / vitest 3 migration; elliptic has no fix.
… lint rule

testing-library/await-async-utils read the wait parameter of a local debounce(func, wait) as Testing Library's deprecated wait(), failing yarn lint and therefore the pre-push hook. Renamed to delayMs; template.js is injected as raw text, so nothing else changes.
Formatting only. The pre-push hook runs yarn prettify and rewrote these four files on every push, leaving them modified in the working tree.
npm deprecates lodash 4.18.0 as a bad release, and ^4.18.0 still
admitted it. The installed version stays 4.18.1; only the direct
dependency, the resolution and its RESOLUTIONS.md entry change.
@anagperal anagperal changed the title Fix/dependency vulnerabilities [Security] Fix dependency vulnerabilities Sep 28, 2026
@bundlemon

bundlemon Bot commented Sep 28, 2026

Copy link
Copy Markdown

BundleMon

No change in files bundle size

Groups updated (1)
Status Path Size Limits
✅ Build Folder
./**/*
1018.12KB (+21.32KB +2.14%) +20%

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

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