Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider removing/replacing update-notifier #1961

Closed
Labels

Comments

@abalabahaha
Copy link

This is the dependency tree I got from installing nodemon in an empty project:

└─┬ nodemon@2.0.15
  ├─┬ chokidar@3.5.2
  │ ├─┬ anymatch@3.1.2
  │ │ ├── normalize-path@3.0.0 deduped
  │ │ └── picomatch@2.3.0
  │ ├─┬ braces@3.0.2
  │ │ └─┬ fill-range@7.0.1
  │ │   └─┬ to-regex-range@5.0.1
  │ │     └── is-number@7.0.0
  │ ├── fsevents@2.3.2
  │ ├─┬ glob-parent@5.1.2
  │ │ └── is-glob@4.0.3 deduped
  │ ├─┬ is-binary-path@2.1.0
  │ │ └── binary-extensions@2.2.0
  │ ├─┬ is-glob@4.0.3
  │ │ └── is-extglob@2.1.1
  │ ├── normalize-path@3.0.0
  │ └─┬ readdirp@3.6.0
  │   └── picomatch@2.3.0 deduped
  ├─┬ debug@3.2.7
  │ └── ms@2.1.3
  ├── ignore-by-default@1.0.1
  ├─┬ minimatch@3.0.4
  │ └─┬ brace-expansion@1.1.11
  │   ├── balanced-match@1.0.2
  │   └── concat-map@0.0.1
  ├── pstree.remy@1.1.8
  ├── semver@5.7.1
  ├─┬ supports-color@5.5.0
  │ └── has-flag@3.0.0
  ├─┬ touch@3.1.0
  │ └─┬ nopt@1.0.10
  │   └── abbrev@1.1.1
  ├── undefsafe@2.0.5
  └─┬ update-notifier@5.1.0
    ├─┬ boxen@5.1.2
    │ ├─┬ ansi-align@3.0.1
    │ │ └── string-width@4.2.3 deduped
    │ ├── camelcase@6.2.1
    │ ├── chalk@4.1.2 deduped
    │ ├── cli-boxes@2.2.1
    │ ├─┬ string-width@4.2.3
    │ │ ├── emoji-regex@8.0.0
    │ │ ├── is-fullwidth-code-point@3.0.0
    │ │ └─┬ strip-ansi@6.0.1
    │ │   └── ansi-regex@5.0.1
    │ ├── type-fest@0.20.2
    │ ├─┬ widest-line@3.1.0
    │ │ └── string-width@4.2.3 deduped
    │ └─┬ wrap-ansi@7.0.0
    │   ├── ansi-styles@4.3.0 deduped
    │   ├── string-width@4.2.3 deduped
    │   └── strip-ansi@6.0.1 deduped
    ├─┬ chalk@4.1.2
    │ ├─┬ ansi-styles@4.3.0
    │ │ └─┬ color-convert@2.0.1
    │ │   └── color-name@1.1.4
    │ └─┬ supports-color@7.2.0
    │   └── has-flag@4.0.0
    ├─┬ configstore@5.0.1
    │ ├─┬ dot-prop@5.3.0
    │ │ └── is-obj@2.0.0
    │ ├── graceful-fs@4.2.8
    │ ├─┬ make-dir@3.1.0
    │ │ └── semver@6.3.0
    │ ├─┬ unique-string@2.0.0
    │ │ └── crypto-random-string@2.0.0
    │ ├─┬ write-file-atomic@3.0.3
    │ │ ├── imurmurhash@0.1.4
    │ │ ├── is-typedarray@1.0.0
    │ │ ├── signal-exit@3.0.6
    │ │ └─┬ typedarray-to-buffer@3.1.5
    │ │   └── is-typedarray@1.0.0 deduped
    │ └── xdg-basedir@4.0.0 deduped
    ├── has-yarn@2.1.0
    ├── import-lazy@2.1.0
    ├─┬ is-ci@2.0.0
    │ └── ci-info@2.0.0
    ├─┬ is-installed-globally@0.4.0
    │ ├─┬ global-dirs@3.0.0
    │ │ └── ini@2.0.0
    │ └── is-path-inside@3.0.3
    ├── is-npm@5.0.0
    ├── is-yarn-global@0.3.0
    ├─┬ latest-version@5.1.0
    │ └─┬ package-json@6.5.0
    │   ├─┬ got@9.6.0
    │   │ ├── @sindresorhus/is@0.14.0
    │   │ ├─┬ @szmarczak/http-timer@1.1.2
    │   │ │ └── defer-to-connect@1.1.3
    │   │ ├─┬ cacheable-request@6.1.0
    │   │ │ ├─┬ clone-response@1.0.2
    │   │ │ │ └── mimic-response@1.0.1 deduped
    │   │ │ ├─┬ get-stream@5.2.0
    │   │ │ │ └── pump@3.0.0 deduped
    │   │ │ ├── http-cache-semantics@4.1.0
    │   │ │ ├─┬ keyv@3.1.0
    │   │ │ │ └── json-buffer@3.0.0
    │   │ │ ├── lowercase-keys@2.0.0
    │   │ │ ├── normalize-url@4.5.1
    │   │ │ └─┬ responselike@1.0.2
    │   │ │   └── lowercase-keys@1.0.1 deduped
    │   │ ├─┬ decompress-response@3.3.0
    │   │ │ └── mimic-response@1.0.1 deduped
    │   │ ├── duplexer3@0.1.4
    │   │ ├─┬ get-stream@4.1.0
    │   │ │ └─┬ pump@3.0.0
    │   │ │   ├─┬ end-of-stream@1.4.4
    │   │ │   │ └── once@1.4.0 deduped
    │   │ │   └─┬ once@1.4.0
    │   │ │     └── wrappy@1.0.2
    │   │ ├── lowercase-keys@1.0.1
    │   │ ├── mimic-response@1.0.1
    │   │ ├── p-cancelable@1.1.0
    │   │ ├── to-readable-stream@1.0.0
    │   │ └─┬ url-parse-lax@3.0.0
    │   │   └── prepend-http@2.0.0
    │   ├─┬ registry-auth-token@4.2.1
    │   │ └─┬ rc@1.2.8
    │   │   ├── deep-extend@0.6.0
    │   │   ├── ini@1.3.8
    │   │   ├── minimist@1.2.5
    │   │   └── strip-json-comments@2.0.1
    │   ├─┬ registry-url@5.1.0
    │   │ └── rc@1.2.8 deduped
    │   └── semver@6.3.0
    ├─┬ pupa@2.1.1
    │ └── escape-goat@2.1.1
    ├─┬ semver-diff@3.1.1
    │ └── semver@6.3.0
    ├─┬ semver@7.3.5
    │ └─┬ lru-cache@6.0.0
    │   └── yallist@4.0.0
    └── xdg-basedir@4.0.0

update-notifier pulls in more dependencies than the rest of nodemon.

I personally think that the drawbacks from keeping outweigh the benefits:

  1. The attack surface is increased, and having many dependencies makes it harder to vet the nodemon dependency tree.
    • Over the years, several vulnerability reports for nodemon dependencies have come from the update-notifier tree. Not all of the vulnerabilities affect nodemon, but again, it's not easy to immediately tell.
    • Dependency chain attacks are becoming more common.
    • Currently, npm outdated reports that about 70 requirements are at least 1 major version behind. I'm sure that some of the updates are not currently necessary, but perhaps they may soon.
  2. In the ~8 years since update-notifier was added, the ecosystem has improved visibility and handling of dependency updates. We have npm outdated and yarn upgrade-interactive, and npx nodemon without an explicit dependency will try to run the latest version by default.

Thoughts?

@remy
Copy link
Owner

remy commented Dec 7, 2021

I don't disagree, but you're point (2) doesn't address what update notifier solves: automatic notification of upgrade.

All other solutions require the user to specifically ask whether there's an upgrade (potentially one that does fix a vuln).

I strongly believe that this project needs something like upgrade notifier, though I'm not convinced it requires that particular dep or any of it's complexity...

@aledalgrande
Copy link

Just my 2c, but I agree with OP. Currently update-notifier has vulnerabilities in its dependencies, some that don't seem to be actively maintained (e.g. nexdrew/ansi-align#61).

Yes, it adds the ability to automatically notify, but we have other specialized tools nowadays for that that run in CI. What we don't have right now is the ability to update that ansi dep that has a security issue. Removing so many dependencies from Nodemon would increase security considerably.

Let me know what you think and if you need help.

@remy
Copy link
Owner

remy commented Jan 4, 2022

I've already agreed that I'd rather not have the dependency. What I'd need to do to remove the dep is to have a bespoke, nodemon specific system to notify of updates. In my head that would probably check an npm endpoint for the current version and compare to the local version, along with a backoff (i.e. do it once a week, or even opt-out), then show a notice.

@jimmywarting
Copy link

jimmywarting commented Feb 14, 2022

👍 on removing it

it is a waste of install time of having to download and exec all of this every time some CI needs to build.

@remy
Copy link
Owner

remy commented Feb 14, 2022

@jimmywarting it's a waste of time including nodemon as part of your CI dependencies… seems like something you wouldn't want to do.

@jimmywarting
Copy link

nodemon is in there with eslint and everything else in dev devdependencies, everytime a PR comes in it must download all dev dependencies as well...

i think a dependabot or something is a better solution.
another thing that you can do is marking older version on npm as deprecated and tag a older release with something like

v1.x is deprecated and don't get any more security patches, update to v2

that way we will get the notification too.

@jimmywarting
Copy link

jimmywarting commented Feb 18, 2022

I would rather have something as small and dependency free version like this running each and every time than having to load 84 modules and risk getting any security issues

const fs = require('node:fs/promise')
const https = require('node:https')

https.get('https://registry.npmjs.org/nodemon', async response => {
    let body = ''
    for await (const chunk of response) body += chunk
    const json = JSON.parse(body)
    const latest = json['dist-tags']['latest'].split('-')[0]
    const pkg = await fs.readFile(`${__dirname}/../../package.json`, 'utf8')
    const pkgJson = JSON.parse(pkg)
    if (latest.localeCompare(pkgJson.version, 'en', {numeric: true}) === -1) {
        console.info(`New version of nodemon is available update to ${latest}`)
    }
})

// haven't tested this code but should work

but preferable nothing at all - just run npm deprecate nodemon@2.0.2 new version available, update to 2.1.0

every sub dependency that you have no control over is a potentially security risk

@remy
Copy link
Owner

remy commented Feb 18, 2022

Pop it in a PR (and probably test!), but yeah, I already agreed: #1961 (comment)

@danepowell
Copy link

Another vulnerability introduced by update-notifier and unlikely to be resolved on its own: #2023

@lorand-horvath
Copy link

lorand-horvath commented Jun 24, 2022

It's worth mentioning that upgrading to a newer version of update-notifier@6 in nodemon@2.0.17 https://github.com/yeoman/update-notifier/releases/tag/v6.0.0 didn't work because @sindresorhus has chosen to completely switch to ES modules, dropping support for CommonJS modules, more on that here https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c - very interesting read! So packages dependent on anything newer from his repos are subject to this problem of incompatibility.

Specifically, update-notifier@5 has a transient dep on got@9 which I reported here sindresorhus/got#2067 but I don't think the vulnerability fix will be backported to got v9 from the ESM-only v12.

@Axent96
Copy link

Axent96 commented Jun 28, 2022

related #2039 & #2040

@DesignByOnyx
Copy link

For those worried about CI and other environments where you need dev dependencies but not things like nodemon, this is what I use optionalDependecies for. I consider optional deps to be "dev dependencies which are not required for building or running tests". Nodemon is usually the number 1 candidate for this.

# make nodemon optional
npm i nodemon -O

Then in your CI/CD/Docker/Whatever:

npm ci --no-optional

@remy remy closed this as completed in #2033 Jul 5, 2022
remy pushed a commit that referenced this issue Jul 5, 2022
Closes #1961
Closes #2028

- Fixes security issue with got (CVE-2022-33987)
- Replace update-notifier with simple-update-notifier which does the same thing but has one dependency (semver) rather than several
- Same caching settings as update-notifier

Congratulations and thanks to @alexbrazier 👏 🥇 ❤️
@github-actions
Copy link

github-actions bot commented Jul 5, 2022

🎉 This issue has been resolved in version 2.0.19 🎉

The release is available on:

Your semantic-release bot 📦🚀

@aledalgrande
Copy link

thank you @remy!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment