Remix.run Logo
__MatrixMan__ 5 days ago

If you end up with bits that hash to 0xabc123 and I end up with bits that hash to 0x456def and we both think we installed fooapp version 7.8.9, there's nothing about the version number that tells us which one of us has been hacked.

But if we both attempt to install 0x456def, it's clear that whoever has 0xabc123 is in trouble. This is especially important in cases where you might need a package while you're on a separate network partition than npm. Any peer can provide it and you know it hasn't been tampered with because if it had been it would have a different hash.

mort96 5 days ago | parent [-]

> If you end up with bits that hash to 0xabc123 and I end up with bits that hash to 0x456def and we both think we installed fooapp version 7.8.9, there's nothing about the version number that tells us which one of us has been hacked.

If this happens, then either the NPM registry has been compromised or my system's 'npm' program or your system's 'npm' program has been compromised.

If the discrepancy is due to one of us running a malicious 'npm', then that malicious 'npm' CLI program could've just not flagged the signature mismatch, so specifying a hash doesn't help us anything.

If both of us are using a non-compromised 'npm' program, and the NPM registry isn't compromised, then we will never be in a situation where my "fooapp version 7.8.9" and your "fooapp version 7.8.9" differs. If a malicious actor compromises an account with publish access for the fooapp package, then all the malicious actor can do is publish a new "fooapp version 7.8.10" that has malware. That's what has happened in every single one of these high profile NPM hacks. You can't retroactively change old versions of your own packages. So to protect against this kind of attack (which, again, means every single NPM hack to date), just not auto-upgrading between minor versions is enough.

To protect against a compromised NPM registry, I agree that we should have package checksums living in our git repositories. But NPM already has that: the package-lock.json contains checksums. I don't understand what it would give us to have that checksum in the package.json instead of the package-lock.json.

__MatrixMan__ 3 days ago | parent [-]

package.lock only protects after the package has been locked though. If I want to say to you:

> I've audited fooapp==7.8.9 and I believe it is both functional and free of malware

You might act on that information by installing it and locking it to a hash. In this scenario we've missed an opportunity to compare hashes. Maybe you end up with a different one due to a problem with NPM or with one of our connections to it (it's a high value target, so CA's behaving badly isn't out of the question, nor is it being compromised).

If we instead deal in hashes up front, we know that we're talking about the same thing. Also, maybe we're not on the same network partition as NPM for some reason. If you've got a hash for the package, you can get it from whoever happens to have it and you can know it hasn't been tampered with. If you're using names you can't really trust it unless you got it from NPM. In addition to the maybe-NPM-is-inaccessable problems, names create additional load on NPM. Odds are we're in the same room when this conversation happens, so the network path between us is much more likely to be stable, high bandwidth, and free of attackers than the path between each of us and NPM.