npm / cli

the package manager for JavaScript
https://docs.npmjs.com/cli/
Other
8.49k stars 3.17k forks source link

[BUG] Incorrect "resolved" URL in package-lock.json #3635

Open alexghr opened 3 years ago

alexghr commented 3 years ago

Is there an existing issue for this?

Current Behavior

npm resolved a dependency to the wrong archive on the registry. Snippet from my package-lock.json

"node_modules/@babel/types": {
      "version": "7.15.0",
      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.9.tgz",
      "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==",

Notice that the version is 7.15.0 but the resolved field points at types-7.14.9.tgz. The integrity check matches 7.15.0's shasum. I'm not sure how this happened, but on this particular branch I did end up having to resolve conflicts automatically using npm install.

I've been debugging this for a couple of hours because this build only failed to install while creating a Docker image (so basically installing from a clean slate), while it worked fine locally, where I had a full npm cache. Locally I could successfully install both with npm install and npm ci. Forcefully clearing the cache (with npm cache clear --force) recreated the issue locally as well.

Expected Behavior

npm should resolve packages to the right archive for the specified package version.

Steps To Reproduce

Not sure how this happened. I suspect it was caused by solving git conflicts with npm install.

Environment

nlf commented 2 years ago

it seems extremely likely this happened when merging the git conflicts.

the reason it works with a warm cache is because given the presence of the integrity field, we can retrieve content based on that data alone. with an empty cache, however, we fetch the tarball we're instructed to fetch (the resolved field) and then compare its hash to the provided integrity. this fails, for obvious reasons.

fixing this, however, would mean that we need to revalidate the tarball url for every package before we attempt to fetch it, which would incur a significant performance cost if we did for every install. it's also only relevant for situations like this where the resolved field was somehow modified outside of npm.

one approach i can think of to address this would be to add a phase to npm doctor that does this validation of your package-lock.json for you. that way we don't take the performance hit at install time for everyone, but for folks who do encounter a similar problem they would at least have some means of repairing it. i'm going to leave this issue open for now to track that need.