Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Most package managers have lockfiles. Yes, npm's decision to have both "npm install" and "npm ci", just so you can confuse and mislead developers, is a bit silly.

But Ruby's Bundler, for example, has been refusing to run your code if your lockfile is inconsistent for as long as I remember.

Locking dependencies is, generally, a solved problem across most ecosystems (despite node botching its UX). Go doesn't get to claim that it's superior here.

But of course, supply chain attacks are still possible with lock files. Because somebody is going to update your dependencies at some point (often for security reasons). And at that point you might be pulling in a malicious dependency which you haven't carefully vetted (because nobody has time to vet all their dependencies thoroughly nowadays).

That's still an unsolved problem, as far as I know. I don't think that Go has solved it.



> Most package managers have lockfiles

> Locking dependencies is, generally, a solved problem across most ecosystems

As someone who is building a package manager for work, and has looked at pretty much every package manager out there (and their ecosystem adoption), I can only say that those don't reflect the current reality of package management (no matter how much I wish it were true).

Bundler was the first mainstream package manager to adopt a lockfile (AFAIK) a mere 12 years ago. Many many language ecosystems predate that and are still lacking lockfiles (or even widespread adoption of a single compatible package manager).

NPM only got lockfiles 5 years ago (after being pressured by yarn). Gradle got them less than 3.5 years ago, and Maven still doesn't have them (though a niche plugin for it exists). The Python ecosystem is still a hot mess, with ~3 competing solutions (Poetry, Pipenv, Conda), of which Conda just got a 1.0 of their decent conda-lock incubation project a month ago, but due to how setuputils works, the cross-platform package management story is broken almost beyond recovery. In Conan lockfiles are still an experimental feature today.

I could go on and on, but I hope that I could paint a picture that while one could argue that with the advent of lockfiles, locking dependencies has become a solved problem _conceptually_, the current status of implementation across ecosystems is still horrible. I'm also constantly amazed about how little love is put into package managers in most language communities, even though they are so crucial for their respective ecosystems.

As far as I can tell nowadays Go does have one of the better package managers, which given their horrible starting point is quite the feat. As a nice side-effect of experiments in the Go package ecosystem, one of the people working on go dep also created one of the best resources around package managers: https://medium.com/@sdboyer/so-you-want-to-write-a-package-m...


You are probably right that, practically, not every language has "solved" dependency locking and that I was probably unduly extrapolating from my experiences with ecosystems where this has been solved, but there are enough package managers (Bundler, Yarn, Poetry, that I know of, and from what people claim, also Composer and Cargo) that have solved it so that go claiming credit for it seems unwarranted. If anything, this should be credited to Bundler (though it's possible that it wasn't the first package manager to do so).

I can give no credit to npm, it would never have had lockfiles if not for yarn, and even its current attempt seems half-assed.

Python has the problem of too many package managers, some which are bad, unfortunately (the list of open bugs for Pipenv is especially alarming; I once had to rip it out of a project because the dependency resolution failed after half an hour with a stack overflow). That said, poetry solves the problem well and correctly, IMHO.

Over in the Java world, you're right that dependency locking is a bit rarer. But I also think the situation is not nearly as dire there. BOMs, where lists of compatible dependencies are curated, are relatively common, so that alleviates some of the pain. Plus, there seems to be less churn than in some other ecosystems. Still, it would probably be technically better to use dependency locking.


To be fair the title of the article is "How Go Mitigates Supply Chain Attacks" not how it solves.

And I think it does a good job at that.

For example if you had any JavaScript package that depended on node-ipc in your project, a simple npm install after cloning the project would download code that tries to corrupt files in your disk if the malicious code determined that your IP was from Russia. (before the malicious package was taken down/fixed)

With Go you would have to explicitly bump dependency versions. Simply cloning the project and installing dependencies would not have downloaded the malicious version. And bumping would at the very least appear as a diff in a Pull Request.


Yes, node's attempt to include lockfiles is botched, unfortunately. Not only are there UX issues (it's completely unintuitive that you should be using "npm ci", for example), but the lock file can also get corrupted e.g. during a merge conflict and npm performs no sanity checking on it.

I once had a case where a build was suddenly failing. The reason turned out to be that (for whatever reason) a dev had managed to corrupt the lock file, probably during a merge conflict, in such a way that the entry for package A actually contained the URL for package B. It turns out that npm didn't realise that this was inconsistent (with the package.json, and with the npm registry) and downloaded package B but exported it as package A, making the error incredibly hard to pin down.


Doesn't node have lockfiles? Cloning a project and running npm install would install the exact dependencies declared in the lockfile right? To quote the docs[1]:

> The goal of package-lock.json file is to keep track of the exact version of every package that is installed so that a product is 100% reproducible in the same way even if packages are updated by their maintainers.

[1]: https://nodejs.dev/learn/the-package-lock-json-file


Nope, you need to run `npm ci` to guarantee that you don't write a new lockfile.


Also the lockfiles are not recursive. i.e. they don't apply to the dependencies you install or their transitive deps.


Maven and gradle don't have lockfiles(by default), and have never really had a serious need for them, because dependency declarations generally don't use ranges. The central repositories don't allow versions to be replaced, and artifacts are all signed with PGP keys of the developers(although most people don't verify these).

I've never really seen the value in dependency ranges, they make builds more complicated, and bring minimal value.


As far as I know that doesn't solve the problem for transitive dependencies, which can still be resolved to different versions without a lock file.


No it’s the same behaviour for transitive dependencies, if two libraries require different versions of the same transitive dependency, the newer one is chosen. Deterministic no lock file required.


> if two libraries require different versions of the same transitive dependency, the newer one is chosen.

Unfortunately, this is not how maven works. It picks the version required by the dependency nearest in depth to the project root, breaking ties by first listed in the file. It is deterministic, but it's not what anyone ever wants by default.

(This is called "dependency mediation" if you want to Google it.)


OK, but that has a whole host of other issues such as the dependency that relies on the older version potentially breaking with the newer version. I think BOMs get around this issue, hence why they're so common, but then it just means that you trade one issue for the other and that's why you have different solutions. A Ruby project, for example, doesn't need BOMs.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: