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

package-lock.json (missing resolved/integrity) not noticed and not repaired automatically by npm #4460

Open
2 tasks done
DavHau opened this issue Feb 23, 2022 · 23 comments
Open
2 tasks done
Labels
Bug thing that needs fixing Priority 2 secondary priority issue Release 8.x work is associated with a specific npm 8 release

Comments

@DavHau
Copy link

DavHau commented Feb 23, 2022

Is there an existing issue for this?

  • I have searched the existing issues

This issue exists in the latest npm version

  • I am using the latest npm

Current Behavior

In order to assure reproducible installations, every package listed in a package-lock.json which is fetched from a registry should contain a resolved and integrity field.

This doesn't seem to be the case looking at some existing lockfileVersion = 2 based file.
See for example: https://raw.githubusercontent.com/directus/directus/2938821be05eaf195872c34eed709ac9b4a430b4/package-lock.json

Inspecting the entries for camelcase@6.2.0 (and many others), neither resolved nor integrity exist.

Checking out the repository and executing npm install happily installs camelcase@6.2.0 while:

  • not complaining about the missing integrity
  • not adding the missing information to the package-lock.json file

To fix the lock file, one currently has to:

  • delete all node_modules directories
  • delete the package-lock.json file
  • execute npm install

Expected Behavior

  • When the integrity field is missing for a package, a warning/error should be shown to the user
    (the problem should be of equivalent importance than a mismatching integrity)
  • The broken package-lock.json file should be repaired somehow
    (not necessarily automatically, but the user should be informed about the problem and instructed on how to fix it)

Steps To Reproduce

> git clone https://github.com/directus/directus
> cd directus
> git checkout 2938821be05eaf195872c34eed709ac9b4a430b4
> npm install

lock file is still broken (check entry camelcase@6.2.0)

Environment

  • npm: 8.5.1
  • Node.js: v16.14.0
  • OS Name: docker node:16
  • npm config:
; node bin location = /usr/local/bin/node
; cwd = /
; HOME = /root
; Run `npm config ls -l` to show all defaults.
@DavHau DavHau added Bug thing that needs fixing Needs Triage needs review for next steps Release 8.x work is associated with a specific npm 8 release labels Feb 23, 2022
@fritzy
Copy link
Contributor

fritzy commented Feb 23, 2022

Warning due to missing integrity might be a good idea, but requires some discussion. This would be a great thing to bring up at an RFC meeting since this would be new behavior. Additionally, npm install without a package spec does not mutate package-lock.json. These behaviors would be new.

We don't currently consider a lack of integrity to be a "broken" package-lock.json, as there are several reasons that a package might not have an integrity field.

If you want to update the package-lock.json, npm install camelcase[@spec].

@DavHau Thanks for filing this! Since this is working as intended, can you please open an RFC issue with some details on how you could/would like to see this changed?

@fritzy fritzy closed this as completed Feb 23, 2022
@fritzy fritzy reopened this Feb 23, 2022
@fritzy
Copy link
Contributor

fritzy commented Feb 23, 2022

I brought this up in today's RFC meeting, and the consensus was that we do want to change this behavior.

Actions:

  • log a warning for missing integrity values (both from lock and package retrieval)
  • if an integrity value is included (like from a registry), update the package-lock.json with that value

This means that we'll get warnings from local file, tarball, and git references, as well as packages from registries that do not include an integrity. It also means that the package-lock.json will mutate upon npm-install even if a spec is not included.

@fritzy fritzy added Priority 2 secondary priority issue and removed Needs Triage needs review for next steps labels Feb 23, 2022
@DavHau DavHau changed the title Broken package-lock.json (missing resolved/integrity) not noticed and not repaired automatically by npm package-lock.json (missing resolved/integrity) not noticed and not repaired automatically by npm Feb 24, 2022
@DavHau
Copy link
Author

DavHau commented Feb 24, 2022

It's good to see that the RFC team wants to move forward on improving this.
Just my 2 cents:

  • I think a missing integrity should be treated as a mismatching integrity.
  • A mismatching/missing integrity should not only trigger a warning, but raise a critical error requiring immediate action by the user.

If the reason integrity hashes are stored within the lock file, is to ensure reproducibility and security, then any mismatch must be treated as a critical error. If it's not, then what is the point of storing integrity hashes in the first place?

EDIT: OK, I just noticed that NPM actually does trigger an error on a integrity mismatch, if the package isn't cached. That's good. But as said, I think a missing integrity should be treated exactly the same (except if there is a good reason why integrity isn't needed, like with local/symlinked modules etc.)

@ljharb
Copy link
Contributor

ljharb commented Feb 24, 2022

Why? If there’s a missing integrity value, you wouldn’t want every install to suddenly start failing. It’s about maximal reproducibility, not guaranteed reproducibility.

@DavHau
Copy link
Author

DavHau commented Feb 24, 2022

If there’s a missing integrity value, you wouldn’t want every install to suddenly start failing.

If you really care about security and reproducibility, you'd want exactly that. Because it protects you from threat/breakages and it gives you the chance to fix it.

AFAIU, the lock file can reference arbitrary tarball URLs and git repos. Integrity checking not being enforced results in a lot of potential attack surface, and things that can go wrong accidentally.

In case you want to ignore the error and continue anyways, you could have a flag like --ignore-integrity.
The important point is, it forces you to do something in a situation where security/reproducibility cannot be guaranteed, which is appropriate.
If the user wants to ignore this circumstance, that's fine, but the decision should be up to the user.

It’s about maximal reproducibility, not guaranteed reproducibility.

Your idea of maximal seems to be different than mine.
If technology allows you to guarantee reproducibility, but you decide to not make use of it, then how can the reproducibility be maximal?

@ljharb
Copy link
Contributor

ljharb commented Feb 24, 2022

It’s as much as is possible, without breaking the common case. If you care that much about security, how did a non-registry dep or a missing integrity value get committed in the first place?

@patcon
Copy link

patcon commented Apr 11, 2022

Note that there's another layer here, where:

  1. one can intentionally break the integrity hash [EDIT: or substitute a non-corrupt hash in place], then
  2. run npm ci, and
  3. npm happily installs all the files, even though the integrity hashes are present, and not even properly-formed [EDIT: or not properly matching files on disk]

This whole area is a real surprise. What is the point of these half-guarantees and false sense of [literal] security? I've been operating as if NPM had my back on this stuff, and it's really jarring to realize that not only does it not have my back, but maintainers seem to be insisting that I shouldn't have my back, and I should... have my own? (I presume the disjunct is for some reason I don't quite grok, and so I'm trying to have good-faith that there's some meta-consideration that makes this make sense for the ecosystem as a whole)

Anyhow, I appreciate you all, but just a little baffled (but also trying to be humble about my bafflement) ❤️

@ljharb
Copy link
Contributor

ljharb commented Apr 11, 2022

@patcon to be clear, if you do intentionally break the hash such that it no longer matches the package being installed, i would definitely expect npm install and npm ci to fail, loudly. If, however, you remove the hash, I would expect npm install to correct that, and npm ci to install anyways.

@patcon
Copy link

patcon commented Apr 11, 2022

Ah ok, so maybe this is another issue. Sorry to conflate. npm ci on v8.3.0 definitely installs without complaint with a broken integrity hash (at least on my machine). I'll try to make a minimal reproduction. (I'm using npm workspaces, and maybe that's complicating things)

@patcon
Copy link

patcon commented Apr 11, 2022

In case helpful, sharing our encounter here: GCTC-NTGC/gc-digital-talent#2414 (comment)

Can you confirm that the Alt Reproduction described there is unexpected for NPM v8.3.0? If so, should this be a new issue, or can we continue discussing here? Thanks!

@ljharb
Copy link
Contributor

ljharb commented Apr 11, 2022

@patcon can you reproduce it with npm v8.6? testing in "not the latest" npm doesn't necessarily help :-)

@patcon
Copy link

patcon commented Apr 11, 2022

heh sorry, just contributing here from an in-use repo (we're stuck at 8.3.0 I recall), but i'll try HEAD later. Wasn't seeing an issue anywhere, so thought I'd raise it sooner. But I'll go off our critical path and do a reproduction once I address it for us. Thanks again @ljharb! 🙌

EDIT: I did bring this up with GitHub Security last month via email channels, and was kinda hinted that they were addressing things, so just trying to do catch-up now. Realizing maybe I wasn't communicating the concern well. Thanks for bearing with us

EDIT2: Bah. What am I saying. This isn't hard. Sorry, my brain was stubbornly staying on my task, but I'll try 8.6.0 🙃

@patcon
Copy link

patcon commented Apr 11, 2022

ok, finito. (Ha!)

node 14.18.1 (stuck on this)
npm 8.6.0
using npm workspaces

both scenarios still hold -- both malformed integrity hashes and well-formed but unmatching hashes run without failure in npm ci

@iggyzap
Copy link

iggyzap commented Apr 25, 2022

Honestly, I am not surprised about this. My default behaviour is to install yarn and use it instead, and set as organisation policy to not to use npm, since it is guaranteed instanity.
We’ve had npm ci sneakily installing updates for about 2 years, now hash validation is ignored ?

just stop using it.

@ath0mas
Copy link

ath0mas commented Apr 30, 2022

My 2 cents for me too ;)

  • a missing integrity should NOT be treated as an error
    fine with nothing like today and before, or a warning, but please not an error (even with a flag to disable it)
  • a mismatching integrity should raise an error
    at least I saw this before with my first experiences with npm 6 ; sad if it has been lost

Why this point of view?
Because some people like me use private package repositories like Nexus that unlike npmjs.com allow or optionally allow in their "npm" repositories to publish and override an already published package with existing target version.
And so, the file hash changes, but integrity can not be easily managed in package-lock.json.
The only way we found to properly deal with it is to manually remove the integrity value specifically for our internal dependencies with nightly logic.

@clomver
Copy link

clomver commented Jun 28, 2022

I appear to have hit this issue running the latest NPM version (8.13.1) - caused by a developer manually updating the versions in both package.json and package-lock.json without updating the integrity value.
I'm running gitbash on Windows 10 Enterprise
Create an empty directory:

npm init -f && npm install
npm i lodash@4.17.20
sed -i s/'4.17.20'/'4.17.21'/g package*
npm ci

-> at this point npm ci runs without complaint.
-> now clear the cached data and re-run npm ci

rm -rf ~/AppData/Local/npm-cache
npm ci

Failed:

npm WARN tarball tarball data for lodash@https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz (sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==) seems to be corrupted. Trying again.
npm ERR! code EINTEGRITY
npm ERR! sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== integrity checksum failed when using sha512: wanted sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== but got sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==. (318961 bytes)

We found this because only completely new starters were hitting the EINTEGRITY error because they did not have any files cached but as soon as you have the cache, NPM no longer respects the integrity check. I would suggest that this is potentially exploitable if someone can intercept the registry and place a malicious package in its place as the package can now have any signature and be of any size since it is not validated.

@Doeke
Copy link

Doeke commented Jul 14, 2022

On 8.12.1, I deleted package-lock and ran npm install in order to remove a stubborn peer dependency, and it generated a new lockfile without any integrity and resolved fields, and any installs afterwards will silently skip integrity checks...

The only way to get back a proper lockfile was to delete both node_modules and package-lock before doing npm install.

The default should be to add the hashes, not to remove them. I imagine there are now a lot of projects with lockfiles that have no integrity hashes, without people being aware of it. Surely this must be avoided?

@hlolli
Copy link

hlolli commented Sep 22, 2022

npm cache clean --force doesn't cut it for me

I need all the integrity and resolved filelds, becuase of cache-only policy,

so what I need to do is to npm install package-missing-integrity-fields --save
then remove it from package.json and do another npm install, then it's settled in the package-lock.json
bit annoying, I wish there was an npm install command that forces every package to be resolved and written into the lockfile.

@vadimdemedes
Copy link

I'm also seeing this and I can't figure out why npm silently deletes integrity and resolved fields from the lock file. I can't bring them back and deleting + re-generating package-lock.json doesn't sound like a good option in a production app.

If anyone has tips on how to restore integrity and resolved without deleting package-lock.json, I'd appreciate it.

@dev-trilobyte
Copy link

@DavHau a missing integrity field MUST NOT be treated the same as a integrity mismatch.
Due to current NPM not being able to create reproducible builds removing the "resolved" and "integrity" field is the only way to work around this if you are using different private repositories (e.g. a dev and prod one inside different firewall zones..)

reproducible build means:
use the same source to create a package should create the same SHA integrity value on publishing this very excakt same package to different NPM registries.
But this is not the case now - the very same published tarball gets a different integrity value on ever publish, therefor it is not possible to used multiple registries.

This use case is similar to the one from @ath0mas but not the same!

but none the less should NPM recreate missing resolved/integrity fields it finds and issue a warning (no error) about it every time it find such a dependency.

@GideonMax
Copy link

GideonMax commented Nov 1, 2023

I brought this up in today's RFC meeting, and the consensus was that we do want to change this behavior.

Actions:

  • log a warning for missing integrity values (both from lock and package retrieval)
  • if an integrity value is included (like from a registry), update the package-lock.json with that value

This means that we'll get warnings from local file, tarball, and git references, as well as packages from registries that do not include an integrity. It also means that the package-lock.json will mutate upon npm-install even if a spec is not included.

Is there a published version of npm with this behavior? If not are there plans of implementing this?
Also, does the modification of the package-lock include adding "resolved" to packages missing that field?

sarcasticadmin added a commit to sarcasticadmin/wave that referenced this issue Mar 27, 2024
Originally these fields were missing due to outstanding issue with npm:

  - npm/cli#4460
  - npm/cli#6301
sarcasticadmin added a commit to sarcasticadmin/wave that referenced this issue Mar 27, 2024
Originally these fields were missing due to outstanding issue with npm:

  - npm/cli#4460
  - npm/cli#6301
sarcasticadmin added a commit to sarcasticadmin/wave that referenced this issue Mar 27, 2024
Originally these fields were missing due to outstanding issue with npm:

  - npm/cli#4460
  - npm/cli#6301
iwanb pushed a commit to iwanb/robotframework-browser that referenced this issue May 29, 2024
iwanb added a commit to iwanb/robotframework-browser that referenced this issue May 29, 2024
iwanb added a commit to iwanb/robotframework-browser that referenced this issue May 29, 2024
@grant-dennison
Copy link

For anyone like me who is looking for a workaround to back-fill these missing fields, I published a small CLI to the npm registry you can use:

npx npm-package-lock-add-resolved

This will fill in any missing resolved and integrity fields in the package-lock.json file of the current directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug thing that needs fixing Priority 2 secondary priority issue Release 8.x work is associated with a specific npm 8 release
Projects
None yet
Development

No branches or pull requests

14 participants