pull down to refresh

I'm trying to figure out if all you need to "opt-out" of 99% of NPM supply chain attacks is to use npm ci, not npm install, see #1213332. npm ci will never automatically update a package without your consent.
However, I'm struggling to find sources for this. If that's actually the case, shouldn't it be all over the place as a reply? Not even this link from a security company mentions the importance of npm ci (next to a lot of other very interesting attack vectors though).
I have only found this comment on HN with the same confusion:
I'm a little confused on one of the excerpts from your article.
Our package-lock.json specified the stable version 1.3.2 or newer, so it installed the latest version 1.3.3
As far as I've always understood, the lockfile always specifies one single, locked version for each dependency, and even provides the URL to the tarball of that version. You can define "x version or newer" in the package.json file, but if it updates to a new patch version it's updating the lockfile with it. The npm docs suggest this is the case as well: https://arc.net/l/quote/cdigautx
And with that, packages usually shouldn't be getting updated in your CI pipeline.
Am I mistaken on how npm(/yarn/pnpm) lockfiles work?
The replies seem to agree with me: use npm ci.
So I think people just don't know about this?
However, to be honest, I knew about this but we were still using npm install ourselves 😬
166 sats \ 19 replies \ @k00b 19h
I don't think npm install auto-updates deps if package-lock.json is complete. If you're using package-lock.json and it's complete, neither should update deps. npm ci is just stricter afaict and if package-lock.json is missing stuff it aborts.
reply
I think that’s right. But really you shouldn’t ever have an incomplete lock file? If you run install and your lock file changes, you have a problem.
reply
50 sats \ 15 replies \ @ek OP 6h
There's so much conflicting information regarding this, online and my own (fuzzy) experience
I also think how @k00b described it is how it should work (it would actually make sense), but I also know that npm install did modify package-lock.json in the past for me.
But maybe that was indeed only when I was working with others and someone forgot to check in package-lock.json after they added it, which would then lead to an incomplete lock file for the next person that pulls.
At this point I guess I have to read the source code of npm to trust what's going on
reply
In my experience, installing only modifies the lock file if it's missing information. Because the point of the lockfile is to tell the package manager exactly what to install. It's not like a suggestion - it is the source of truth. It's only changed if it's missing details, or you specifically tell it to install something new and/or upgrade, which falls under the "missing details" broader label.
reply
50 sats \ 11 replies \ @ek OP 6h
Doesn't that imply that everyone who ran npm install and downloaded the malicious version were using an incomplete lock file?
reply
Yes? Either they didn't have it in their lockfile, or they installed the dependency new while the malicious version was the latest, or they did an upgrade while it was live.
reply
Otherwise, you'd see changes in lockfiles all the time as any number of transitive dependencies are updated within semver constantly.
reply
50 sats \ 8 replies \ @ek OP 6h
Makes sense!
I'm just still confused because the cause doesn't seem to match the amount of confusion. How this can happen (incomplete lock file) doesn't seem to match how often it seems to happen (the internet is full with people complaining about it).
Did all of them also had someone who forget to check in changes to package-lock.json? How else could it happen to have an incomplete lock file? Who modifies their package-lock.json manually or undoes the changes to it (git checkout package-lock.json) and then wonders why npm install changes it again or ...?
But maybe I'm contributing to the confusion around it right now haha
I wish the documentation was more clear when npm install changes package-lock.json. I don't see it mentioning what happens if the lock file is incomplete.
Not sure if this has anything to do with what you guys were talking about, but did you see this? #1213980
reply
0 sats \ 0 replies \ @ek OP 6h
after they added it
*after they added an package
reply
166 sats \ 1 reply \ @k00b 19h
Yep, my understanding too
reply
It’s certainly still a viable attack vector though, because who checks all of their transitive dependencies every time dependabot opens a PR haha
reply