npm/npm — pull request #5137 by glasser (2014-04-24 05:58:54+00:00)
Title: Check SHA before using files from cache

Fixes #3265.

Because 'npm install' *always* writes every package to the cache (even
if it isn't installed from the registry) before installing it, it's easy
to end up in a situation where "npm install foo" installs something
other than the appropriate version from the registry. eg:

npm cache clean
# Install a fork of version 0.0.1:
npm install https://github.com/glasser/npm-cache-corruption/tarball/93c447e
rm -rf node_modules
# Before this commit, this would install the same fork as above
npm install npm-cache-corruption

See https://gist.github.com/glasser/5391502 for more details on the reproduction.

I can imagine that running a SHA-check on every install could be a performance issue. But I really do think that this is a correctness issue worth fixing; we have a wrapper script that essentially always uses `npm install --force` to work around this problem.

If you think this SHA check is too much of a performance hit, there are some other possibilities I could try to implement, such as:

- whenever writing package.tgz, also write its SHA to a second file. This means that instead of actually computing the SHA, you just have to read this file. This could be slightly racy, but probably OK if done right.
- when writing a package to the cache, if it wasn't read directly from the registry, write another file that means essentially "don't trust me, I'm not the real version".
- don't actually write packages that aren't from the registry to the cache at all! I personally don't understand why npm ever writes packages that aren't from the registry to the cache, but this seems pretty core to the design of install so I didn't want to just change it.