Skip to content

Feature/security#394

Merged
Ramon-Jimenez merged 10 commits into
developmentfrom
feature/security
Jun 17, 2026
Merged

Feature/security#394
Ramon-Jimenez merged 10 commits into
developmentfrom
feature/security

Conversation

@xurxodev

Copy link
Copy Markdown

📌 References

!!!Important it's necessary merge related PR and re-build github actions to use last changes in workflows!!!

📝 Implementation

  • Migrate to vite
  • Update node to 22
  • Upgrade yarn 4
  • Apply security patches (snyk)

🛡️ Vulnerabilities fixed

Critical

  • form-data: Predictable Boundary (CVE-2025-7783) -> resolution 4.0.4

High

  • axios: SSRF, CSRF, Prototype Pollution, DoS -> direct upgrade 1.13.5 + resolution 1.13.5
  • @babel/runtime (e.g. via @babel/traverse chain): Incomplete List of Disallowed Inputs -> resolution 7.26.10
  • i18next: Prototype Pollution (SNYK-JS-I18NEXT-1065979) -> resolution 19.8.5
  • @remix-run/router (via react-router-dom): XSS (SNYK-JS-REMIXRUNROUTER-14908530) -> direct upgrade react-router-dom 6.30.3

Medium (resolutions)

  • brace-expansion: ReDoS -> resolution 1.1.12
  • glob-parent: ReDoS (CVE-2020-28469) -> resolution 5.1.2
  • i18next: Buffer Overflow / Prototype Pollution (SNYK-JS-I18NEXT-575536, SNYK-JS-I18NEXT-585930) -> resolution 19.8.5
  • lodash / lodash-es: Prototype Pollution -> resolution 4.17.23
  • minimatch: ReDoS -> resolution 3.1.3
  • nanoid: Improper Input Validation (CVE-2024-55565) -> resolution 3.3.8
  • node-fetch: Information Exposure / DoS (SNYK-JS-NODEFETCH-2342118, SNYK-JS-NODEFETCH-674311) -> resolution 2.6.7
  • path-to-regexp: ReDoS (CVE-2024-45296) -> resolution 1.9.0
  • qs: Allocation/Throttling + Prototype Poisoning -> resolution 6.14.2
  • diff: vulnerable transitive version -> resolution 5.2.2
  • debug: vulnerable transitive version -> resolution 4.3.4
  • ua-parser-js: vulnerable transitive version -> resolution 0.7.24
  • jszip: vulnerable transitive version in old transitive paths -> resolution 3.7.0

Direct upgrades applied

  • @dhis2/app-runtime -> 3.12.0
  • @eyeseetea/feedback-component -> 0.3.0
  • @material-ui/core -> 4.12.4
  • @material-ui/icons -> 4.11.3
  • @material-ui/styles -> 4.11.5
  • axios -> 1.13.5
  • lodash -> 4.17.23
  • moment -> 2.29.4
  • react-router-dom -> 6.30.3
  • styled-jsx -> 5.0.0

⚠️ Vulnerabilities not fixed (and reason)

Remaining issue from the latest report (Tested 410 dependencies, 1 issue, 2 vulnerable paths):

Vulnerability Severity Reason
jszip@3.7.0 (Arbitrary File Write via Archive Extraction / Zip Slip, SNYK-JS-JSZIP-3188562) Medium Not yet fixed in this branch state. Snyk recommends upgrading to jszip@3.8.0+; current vulnerable path still resolves to 3.7.0 in 2 paths.

Used plan: Migrate to Yarn 4 with coexistence in other projects

Current situation (example for this repo)

  • Lockfile: yarn.lock is v1 format (Yarn Classic).
  • Config: There is no .yarnrc or .npmrc; there is no packageManager or engines in package.json.
  • Local dependency: "$": "link:./src" in package.json; the link: protocol is compatible with Yarn 4.
  • Node: Yarn 4 requires Node 18+.

How coexistence works

Corepack (included in Node 16.10+) allows you to pin the Yarn version per project using the packageManager field in package.json. You don’t need to change the global Yarn installation on your machine.

Typical setup when you work with multiple projects:

  • Use Corepack only (no global yarn installed with npm -g, uninstall it with npm uninstall -g yarn).
  • Set a default Yarn 1.x for projects without packageManager:
corepack enable
corepack prepare yarn@1.22.22 --activate   # default for old projects
  • In this project, declare:
"packageManager": "yarn@4.12.0"

Result:

  • In this repo, yarn uses Yarn 4.12.0 (as specified in packageManager).
  • In other repos without packageManager, yarn uses Yarn 1.22.22 (or whatever you activated with Corepack).
flowchart LR
  subgraph proyecto_yarn4 [This project]
    A[packageManager: yarn@4.x]
  end
  subgraph otros [Other projects]
    C[No packageManager or yarn@1]
  end
  Corepack[Corepack]
  Corepack --> A
  Corepack --> C
Loading
  • In this repo: running yarn will use the version declared in packageManager (Yarn 4) via Corepack, without needing to vendor Yarn into .yarn/releases.
  • In other projects: if they don’t have packageManager or have a different version, they will keep using your global Yarn (1.x or whatever they use).

Requirement: have Corepack enabled once on the machine (corepack enable). There is no need to install Yarn 4 globally.


Implementation steps

1. One-time machine setup (per developer)

Run this once on your machine (not per project), to let Corepack manage Yarn versions and keep Yarn 1.x as the default for old projects:

# (optional but recommended) remove globally installed Yarn
npm uninstall -g yarn

# enable Corepack (shipped with Node 16.9+ / 14.19+)
corepack enable

# set Yarn 1.x as the default for projects WITHOUT packageManager
corepack prepare yarn@1.22.22 --activate

After this, any project without packageManager will use Yarn 1.22.22, and projects with packageManager: "yarn@4.x.x" will use Yarn 4 via Corepack.

2. Migrate this project to Yarn 4

Recommended order:

  1. Create a safety commit so you can revert if needed.
  2. Add packageManager in package.json with an exact version (for example "yarn@4.12.0"). This way Corepack already knows which version to use before .yarn/releases exists.
  3. Make sure Yarn 4 is being used in this repo (so that yarn set version runs with the right major):
corepack use yarn@4.12.0
yarn --version   # should print 4.12.0
  1. Install Yarn 4 in the project (generates .yarnrc.yml and updates Yarn metadata for the project via Corepack):
yarn set version 4.12.0
  1. node_modules mode: By default Yarn 4 can use PnP. To keep using node_modules (as now) and avoid large changes in tooling (Vite, etc.), in .yarnrc.yml (created with set version) keep or add:
nodeLinker: node-modules
  1. Reinstall and regenerate the lockfile:
yarn install

The lockfile will be converted to Yarn 4 format (yarn.lock with a __metadata header).

There is no need to touch the "$": "link:./src" dependency; the link: protocol is still supported.

3. Update .gitignore

Add typical Yarn 4 entries so cache and installation state are not committed:

  • .yarn/cache (package cache)
  • .yarn/install-state.gz
  • .yarn/unplugged
  • .yarn/build-state.yml
  • .pnp.* (if PnP is used in the future)

Note: When using Corepack and packageManager, it is not required to vendor Yarn into .yarn/releases. This project relies on Corepack to provide the right Yarn version.

4. Scripts and lifecycle
  • postinstall (yarn localize): Still supported in Yarn 4; no changes required.
  • There are no custom pre/post hooks that need to be rewritten according to the migration guide.
5. Documentation

In README.md you can add a short section under Setup to explain that the project uses Yarn 4 + Corepack and how to fix conflicts with a global Yarn 1. For example:

## Setup

```bash
$ nvm use # uses node version in .nvmrc
$ yarn install
```

This project uses Yarn 4 managed by Corepack and declares:

"packageManager": "yarn@4.12.0"
If you have Yarn 1 globally and see a packageManager error

If running yarn shows an error like:

This project's package.json defines "packageManager": "yarn@4.12.0". However the current global version of Yarn is 1.22.x.

do the following once on your machine:

# 1) Remove global Yarn (optional but recommended)
npm uninstall -g yarn

# 2) Enable Corepack (shipped with Node 16.9+ / 14.19+)
corepack enable

# 3) Set Yarn 1.x as the default for projects WITHOUT packageManager
corepack prepare yarn@1.22.22 --activate

Then, in this project (normal case, once Corepack is enabled):

nvm use
yarn install

If for some reason yarn --version still shows 1.x inside this repo, you can force Yarn 4 explicitly:

corepack use yarn@4.12.0
yarn --version   # should now print 4.12.0
yarn install

---

#### Summary of files to update

| File                         | Changes                                                                                                 |
| ---------------------------- | ------------------------------------------------------------------------------------------------------- |
| [package.json](package.json) | Add `"packageManager": "yarn@4.x.x"` (exact version).                                                   |
| `.yarnrc.yml`                | Created by `yarn set version 4`; add `nodeLinker: node-modules` if you want to keep using node_modules. |
| [yarn.lock](yarn.lock)       | Regenerated by `yarn install` (Yarn 4 format).                                                          |
| [.gitignore](.gitignore)     | Add `.yarn/cache`, `.yarn/install-state.gz`, `.yarn/unplugged`, `.yarn/build-state.yml`.                |

---

#### Expected behavior

-   **In this project**: `yarn install`, `yarn build`, `yarn start`, etc. use Yarn 4.
-   **In other projects** (without `packageManager` or with a different version): they keep using whatever Yarn version they already have (1.x, 3.x, etc.) and are not affected by this migration.

If you want Yarn 4 in another project in the future, repeat `packageManager` + `yarn set version 4` there and Corepack will ensure Yarn 4 is used only when you are inside that project.

📹 Screenshots/Screen capture

🔥 Testing

- Enable core pack in prepare script
- Add packageManager in package.json
- Install Yarn 4 in the project
- Update .gitignore
- Update README
…time

Upgrade vulnerable direct dependencies flagged by Snyk, including
@dhis2/app-runtime, @eyeseetea/feedback-component, @material-ui/*,
axios, lodash, moment, react-router-dom and styled-jsx.
Adjust runtime integration after upgrades (Provider props for app-runtime,
lodash import in MetadataService, and Vite __dirname define for styled-jsx)
so build and tests remain green.
Upgrade direct dependencies flagged by Snyk, including @dhis2/app-runtime,
@eyeseetea/feedback-component, @material-ui/*, axios, lodash, moment,
react-router-dom and styled-jsx.
Add dependency resolutions to force secure transitive versions for:
axios, @babel/runtime, i18next, brace-expansion, form-data, glob-parent,
lodash, minimatch, nanoid, node-fetch, path-to-regexp and qs.
- @babel/runtime, i18next, brace-expansion, form-data, glob-parent, lodash-es,
  minimatch, nanoid, node-fetch, path-to-regexp, qs, diff, debug, ua-parser-js,
  jszip (and axios aligned across the tree where applicable)
Tests
Replace the shell loop in `update-po` with a `find -exec` based command
to avoid `spawn ENOTDIR` under Corepack/Yarn 4 during pre-push.
@bundlemon

bundlemon Bot commented Mar 24, 2026

Copy link
Copy Markdown

BundleMon

No change in files bundle size

Groups updated (1)
Status Path Size Limits
Build Folder
./**/*
1.74MB (+17.28KB +0.98%) +20%

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

@Ramon-Jimenez Ramon-Jimenez left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xurxodev A couple of things on this one, tested on v42:

  • yarn build fails due to a reference to D2ApiDefault package being imported from d2-api (which is also provoking a conflict with development)
  • After removing this reference and building the app, it compiles and gets installed but when trying to import any Bulk Load template, it throws an error _ is not defined
Image

Thanks!

@xurxodev

Copy link
Copy Markdown
Author

@Ramon-Jimenez for me It's working.

This PR use yarn 4 and it's necessary:
nvm use
yarn install
yarn build

xurxodev@Jorges-MacBook-Pro Bulk-Load % nvm use
Found '/Users/xurxodev/Workspace/EyeSeeTea/web/Bulk-Load/.nvmrc' with version <v22.22.0>
Now using node v22.22.0 (npm v10.9.4)
xurxodev@Jorges-MacBook-Pro Bulk-Load % yarn 
➤ YN0088: A new stable version of Yarn is available: 4.16.0!
➤ YN0088: Upgrade now by running yarn set version 4.16.0

➤ YN0000: · Yarn 4.12.0
➤ YN0000: ┌ Resolution step
➤ YN0000: └ Completed
➤ YN0000: ┌ Post-resolution validation
➤ YN0060: │ @dhis2/app-runtime is listed by your project with version 3.12.0 (pd00232), which doesn't satisfy what @dhis2/ui-widgets and other dependencies request (^2.11.0).
➤ YN0060: │ react is listed by your project with version 17.0.2 (p00dd6b), which doesn't satisfy what @dhis2/app-runtime and other dependencies request (but they have non-overlapping ranges!).
➤ YN0060: │ react-dom is listed by your project with version 17.0.2 (p7ab5e2), which doesn't satisfy what @dhis2/app-runtime and other dependencies request (but they have non-overlapping ranges!).
➤ YN0060: │ styled-jsx is listed by your project with version 5.0.0 (p9c5a63), which doesn't satisfy what @dhis2/ui-core and other dependencies request (^3.2.0).
➤ YN0002: │ bulk-load@workspace:. doesn't provide @babel/plugin-syntax-flow (p1c4b58), requested by eslint-plugin-flowtype.
➤ YN0002: │ bulk-load@workspace:. doesn't provide @babel/plugin-transform-react-jsx (p0a5ecc), requested by eslint-plugin-flowtype.
➤ YN0002: │ bulk-load@workspace:. doesn't provide @dhis2/ui-constants (p5a647d), requested by @dhis2/ui-widgets.
➤ YN0086: │ Some peer dependencies are incorrectly met by your project; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code.
➤ YN0086: │ Some peer dependencies are incorrectly met by dependencies; run yarn explain peer-requirements for details.
➤ YN0000: └ Completed
➤ YN0000: ┌ Fetch step
➤ YN0000: └ Completed in 0s 498ms
➤ YN0000: ┌ Link step
➤ YN0007: │ core-js@npm:3.20.3 must be built because it never has been before or the last one failed
➤ YN0007: │ core-js@npm:2.6.11 must be built because it never has been before or the last one failed
➤ YN0007: │ esbuild@npm:0.18.20 must be built because it never has been before or the last one failed
➤ YN0007: │ core-js-pure@npm:3.6.5 must be built because it never has been before or the last one failed
➤ YN0007: │ bulk-load@workspace:. must be built because it never has been before or the last one failed
➤ YN0000: └ Completed in 45s 893ms
➤ YN0000: · Done with warnings in 46s 638ms
xurxodev@Jorges-MacBook-Pro Bulk-Load % yarn build
Reading package data: package.json
Validating manifest: ✓ Ok
Writing manifest to: manifest.webapp
Done!
vite v4.5.14 building for production...
node_modules/@tanstack/react-query/build/lib/useQueries.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/useQueries.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/useQuery.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/useQuery.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/QueryClientProvider.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/QueryClientProvider.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/QueryErrorResetBoundary.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/QueryErrorResetBoundary.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/useIsFetching.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/useIsFetching.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/useIsMutating.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/useIsMutating.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/useMutation.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/useMutation.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/isRestoring.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/isRestoring.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/Hydrate.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/Hydrate.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/useInfiniteQuery.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/useInfiniteQuery.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/reactBatchedUpdates.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/reactBatchedUpdates.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/useSyncExternalStore.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/useSyncExternalStore.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/errorBoundaryUtils.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/errorBoundaryUtils.mjs" was ignored.
node_modules/@tanstack/react-query/build/lib/useBaseQuery.mjs (1:0) Module level directives cause errors when bundled, "use client" in "node_modules/@tanstack/react-query/build/lib/useBaseQuery.mjs" was ignored.
node_modules/vm-browserify/index.js (110:11) Use of eval in "node_modules/vm-browserify/index.js" is strongly discouraged as it poses security risks and may cause issues with minification.
✓ 14157 modules transformed.
build/index.html                                      1.13 kB │ gzip:     0.54 kB
build/assets/logo-eyeseetea-c657528c.png             16.20 kB
build/assets/index-4ecb8df1.css                       2.20 kB │ gzip:     0.88 kB
build/assets/02.history-permissions-e3809381.js       0.34 kB │ gzip:     0.24 kB
build/assets/01.settings-permissions-80596cbf.js      1.09 kB │ gzip:     0.56 kB
build/assets/index-8bf9b982.js                    4,554.75 kB │ gzip: 1,264.76 kB

(!) Some chunks are larger than 500 kBs after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
✓ built in 14.58s
Reading package data: package.json
Validating manifest: ✓ Ok
Writing manifest to: build/manifest.webapp
Done!
xurxodev@Jorges-MacBook-Pro Bulk-Load % 

@Ramon-Jimenez

Copy link
Copy Markdown

@xurxodev It does build if you use incoming change instead of what is currently in development. However, I'd say we need to use what is in development (without the D2ApiDefault, but that's coming from development)

In any case, even after the build, the _ is not defined issue is still there, it is not possible to import any template using a Bulk Load app generated with this branch on v42

image

xurxodev added 2 commits June 12, 2026 06:40
…mport

`toDetails()` used `_.pick` without importing lodash, causing
`ReferenceError: _ is not defined` when saving history after a
template import in the Vite production bundle.
@xurxodev

Copy link
Copy Markdown
Author

@Ramon-Jimenez Merged with development, fixed the bug and testing importing a file

@Ramon-Jimenez

Copy link
Copy Markdown

@xurxodev Thanks. It is now possible to import templates, but for some reason it seems we lost the modal window that prompts when data is already available in the dataset for the same periods. This one:

image

It is displaying on v40 but not on v42. I guess we haven't lost this feature as part of this PR, but in any case please let's fix it.

@Ramon-Jimenez

Copy link
Copy Markdown

Approving this one, will move issue about modal window disappearing on v42 to another specific ticket.

@Ramon-Jimenez Ramon-Jimenez merged commit f167c20 into development Jun 17, 2026
6 checks passed
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.

2 participants