Stylus - malicious npm package removed but present in Frappe. Fails to build Docker

I was deploying Frappe/ERPNext like I usually do with the CI/CD pipeline and it failed suddenly. Looking at build log and this is the error where it happens.

	[1/5] Validating package.json...
	[2/5] Resolving packages...
	[3/5] Fetching packages...
	verbose 1.112152251 Performing "GET" request to "https://registry.yarnpkg.com/codex-tooltip/-/codex-tooltip-1.0.5.tgz".
	verbose 1.127663792 Performing "GET" request to "https://registry.yarnpkg.com/codex-notifier/-/codex-notifier-1.1.2.tgz".
	verbose 1.140400959 Performing "GET" request to "https://registry.yarnpkg.com/html-janitor/-/html-janitor-2.0.4.tgz".
	verbose 1.149154709 Performing "GET" request to "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz".
	verbose 1.155934626 Performing "GET" request to "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.16.tgz".
	verbose 1.259522459 Performing "GET" request to "https://registry.yarnpkg.com/@codexteam/icons/-/icons-0.1.0.tgz".
	verbose 1.265948167 Performing "GET" request to "https://registry.yarnpkg.com/@editorjs/editorjs/-/editorjs-2.26.5.tgz".
	verbose 1.268913251 Performing "GET" request to "https://registry.yarnpkg.com/@frappe/esbuild-plugin-postcss2/-/esbuild-plugin-postcss2-0.1.3.tgz".
	verbose 1.582482292 Performing "GET" request to "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz".
	verbose 1.604844001 Performing "GET" request to "https://registry.yarnpkg.com/less/-/less-4.2.0.tgz".
	verbose 1.681366626 Performing "GET" request to "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-4.3.1.tgz".
	verbose 1.718448542 Performing "GET" request to "https://registry.yarnpkg.com/resolve-file/-/resolve-file-0.3.0.tgz".
	verbose 1.749285209 Performing "GET" request to "https://registry.yarnpkg.com/sass/-/sass-1.69.5.tgz".
	verbose 1.846532417 Performing "GET" request to "https://registry.yarnpkg.com/stylus/-/stylus-0.62.0.tgz".
	verbose 1.861071042 Performing "GET" request to "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz".
	verbose 1.865105917 Performing "GET" request to "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.1.tgz".
	verbose 1.914686084 Error: https://registry.yarnpkg.com/stylus/-/stylus-0.62.0.tgz: Request failed "404 Not Found"
	at ResponseError.ExtendableBuiltin (/home/frappe/.nvm/versions/node/v20.19.2/lib/node_modules/yarn/lib/cli.js:696:66)
	at new ResponseError (/home/frappe/.nvm/versions/node/v20.19.2/lib/node_modules/yarn/lib/cli.js:802:124)
	at Request.<anonymous> (/home/frappe/.nvm/versions/node/v20.19.2/lib/node_modules/yarn/lib/cli.js:66750:16)
	at Request.emit (node:events:524:28)
	at module.exports.Request.onRequestResponse (/home/frappe/.nvm/versions/node/v20.19.2/lib/node_modules/yarn/lib/cli.js:142287:10)
	at ClientRequest.emit (node:events:524:28)
	at HTTPParser.parserOnIncomingClient (node:_http_client:702:27)
	at HTTPParser.parserOnHeadersComplete (node:_http_common:118:17)
	at TLSSocket.socketOnData (node:_http_client:544:22)
	at TLSSocket.emit (node:events:524:28)
	info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
	error Error: https://registry.yarnpkg.com/stylus/-/stylus-0.62.0.tgz: Request failed "404 Not Found"
	at ResponseError.ExtendableBuiltin (/home/frappe/.nvm/versions/node/v20.19.2/lib/node_modules/yarn/lib/cli.js:696:66)
	at new ResponseError (/home/frappe/.nvm/versions/node/v20.19.2/lib/node_modules/yarn/lib/cli.js:802:124)
	at Request.<anonymous> (/home/frappe/.nvm/versions/node/v20.19.2/lib/node_modules/yarn/lib/cli.js:66750:16)
	at Request.emit (node:events:524:28)
	at module.exports.Request.onRequestResponse (/home/frappe/.nvm/versions/node/v20.19.2/lib/node_modules/yarn/lib/cli.js:142287:10)
	at ClientRequest.emit (node:events:524:28)
	at HTTPParser.parserOnIncomingClient (node:_http_client:702:27)
	at HTTPParser.parserOnHeadersComplete (node:_http_common:118:17)
	at TLSSocket.socketOnData (node:_http_client:544:22)
	at TLSSocket.emit (node:events:524:28)

Looking at the npm package stylus - npm it seems like it has been removed with the message:

This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.

Please refer to www.npmjs.com/advisories?search=stylus for more information.

Stylus is used in frappe/esbuild-plugin-postcss2

Update 1: News Articles.

Update 2:

Update 3:
Seems like it has been a mistake and the package has been removed accidentally.

Is there any workaround to build a docker image ?

Important: This is a temporary fix. You must actively monitor the official stylus GitHub issue for updates. Once the package is correctly available on npm/Yarn and the flagging issue is resolved, you should revert these changes to rely on standard package management.

Step 1: Modify Your package.json

To override the stylus package, you need to add both overrides (for npm) and resolutions (for Yarn) to the root package.json file of your frappe-framework project. This ensures that the specified stylus version is enforced, regardless of the package manager used.

Add the following section to your package.json:

  "overrides": {
    "stylus": "github:stylus/stylus#0.64.0"
  },
  "resolutions": {
    "stylus": "github:stylus/stylus#0.64.0"
  }

Your complete package.json file should look like this after the modification:

{
  "name": "frappe-framework",
  "scripts": {
    "build": "node esbuild",
    "production": "node esbuild --production",
    "watch": "node esbuild --watch",
    "coverage:report": "npx nyc report --reporter=clover"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/frappe/frappe.git"
  },
  "author": "Frappe Technologies Pvt. Ltd.",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/frappe/frappe/issues"
  },
  "engines": {
    "node": ">=18"
  },
  "homepage": "https://frappeframework.com",
  "dependencies": {
    "@editorjs/editorjs": "~2.26.3",
    "@frappe/esbuild-plugin-postcss2": "^0.1.3",
    "@headlessui/vue": "^1.7.16",
    "@popperjs/core": "^2.11.2",
    "@redis/client": "^1.5.8",
    "@sentry/browser": "^7.119.1",
    "@vue-flow/background": "^1.1.0",
    "@vue-flow/core": "^1.16.2",
    "@vue/component-compiler": "^4.2.4",
    "@vueuse/core": "^9.5.0",
    "ace-builds": "^1.4.8",
    "air-datepicker": "github:frappe/air-datepicker",
    "autoprefixer": "10",
    "awesomplete": "^1.1.5",
    "bootstrap": "4.6.2",
    "chalk": "^2.3.2",
    "cliui": "^7.0.4",
    "cookie": "^0.4.0",
    "cropperjs": "^1.5.12",
    "cssnano": "^5.0.0",
    "driver.js": "^0.9.8",
    "editorjs-undo": "0.1.6",
    "esbuild": "^0.14.29",
    "esbuild-plugin-vue3": "^0.3.0",
    "fast-deep-equal": "^2.0.1",
    "fast-glob": "^3.2.5",
    "frappe-charts": "2.0.0-rc27",
    "frappe-datatable": "1.19.0",
    "frappe-gantt": "^0.6.0",
    "frappe-quill-image-resize": "^3.0.9",
    "highlight.js": "^10.4.1",
    "html5-qrcode": "^2.3.8",
    "jquery": "3.7.0",
    "js-sha256": "^0.9.0",
    "jsbarcode": "^3.11.0",
    "launch-editor": "^2.2.1",
    "localforage": "^1.10.0",
    "md5": "^2.3.0",
    "moment": "^2.29.4",
    "moment-timezone": "^0.5.35",
    "pinia": "^2.0.23",
    "plyr": "^3.7.8",
    "popper.js": "^1.16.0",
    "postcss": "8",
    "quill": "2.0.3",
    "quill-magic-url": "^3.0.0",
    "qz-tray": "^2.0.8",
    "rtlcss": "^4.0.0",
    "sass": "^1.63.0",
    "showdown": "^2.1.0",
    "socket.io": "^4.7.1",
    "socket.io-client": "^4.7.1",
    "sortablejs": "^1.15.0",
    "superagent": "^8.0.0",
    "touch": "^3.1.0",
    "vue": "^3.3.0",
    "vue-router": "^4.1.5",
    "vuedraggable": "^4.1.0",
    "vuex": "4.0.2",
    "yargs": "^17.5.1"
  },
  "nyc": {
    "report-dir": ".cypress-coverage"
  },
  "optionalDependencies": {
    "bufferutil": "^4.0.8",
    "utf-8-validate": "^6.0.3"
  },
  "overrides": {
    "stylus": "github:stylus/stylus#0.64.0"
  },
  "resolutions": {
    "stylus": "github:stylus/stylus#0.64.0"
  }
}

Step 2: Forking and Branching for Frappe Builds

Since the stylus issue might affect various Frappe apps it’s recommended to apply this fix across Frappe apps that have package.json. This involves forking the main frappe repository and any other Frappe apps that contain a package.json file and might be using stylus as a dependency (direct or indirect).

  1. Fork the frappe/frappe repository on GitHub.
  2. Fork any other relevant Frappe applications that might have their own package.json files and depend on stylus.
  3. For each forked repository, create a new branch (e.g., version-15-stylus).
  4. Apply the package.json modifications (as described in Step 1) to this new branch in each of your forks.
  5. Push these branches to your respective forked repositories.

To use frappe fork and branch use FRAPPE_PATH=https://github.com/revant/frappe.git and FRAPPE_BRANCH=version-15-stylus as build args. e.g.

docker build \
  --build-arg=FRAPPE_PATH=https://github.com/revant/frappe \
  --build-arg=FRAPPE_BRANCH=version-15-stylus \
  --build-arg=PYTHON_VERSION=3.11.9 \
  --build-arg=NODE_VERSION=20.19.2 \
  --build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
  --tag=ghcr.io/user/repo/custom:1.0.0 \
  --file=images/custom/Containerfile .

Update your apps.json file to point to these specific branches in your forks. For example, if your apps.json previously referenced the main frappe-app repository, you would update it to:

[
  {
    "url": "https://github.com/your-username/your-frappe-app.git",
    "branch": "version-15-stylus"
  }
  // ... other apps
]

This ensures that your installation uses override to download stylus.

Final Considerations

This approach provides a temporary fix for the stylus dependency problem. Please keep the following in mind:

  • Monitor Official Channels: Continuously track the stylus GitHub issue and official Frappe communications for a permanent resolution.
  • Thorough Testing: After implementing these overrides, perform comprehensive testing of your Frappe instance to ensure no unexpected side effects or regressions have been introduced.
  • Reversion Plan: Once stylus is properly available on npm/Yarn and the incorrect flagging is resolved, revert these overrides and resolutions to rely on standard, officially published packages. This will simplify future dependency management.

UPDATE Just the change in frappe’s package.json worked where frappe+erpnext+crm was used. No need to update apps.json unless builds fail.

8 Likes

Package is now accessible.

1 Like

Yes, problem seems to be fixed and back to normal :slight_smile:

Yes’s available now, thanks for the Update