Live data from Hacker News

How Go mitigates supply chain attacks

go.dev

221–230 of 265 posts

Re: How Go mitigates supply chain attacks

#221
post #68

Earlier quoted context omitted.

This is a pretty genuinely confounding response, and I mean that with absolutely no offense intended. There is a tremendous amount of fighting between devs who prefer Go and Rust, and a tremendous amount of elitism as well, truly from both perspectives. Rust gained a reputation for elitism long before Go did; “Rust Evangelism Strike Force” was never meant to be pejorative, and “Rewrite it in Rust” was never meant to…

Without commenting on anything else here: > “Rust Evangelism Strike Force” was never meant to be pejorative, and “Rewrite it in Rust” was never meant to be a joke Maybe it's just been such a long time, but my recollection was exactly that: both of these terms were invented by outsiders intending to denigrate the Rust community, and became jokes inside the community as a means of recuperating them. Okay, I will mentio…

I won’t comment on Rust Evangelism Strike Force too much; it seemed to be unironically used as a term of endearment at some point, but that could’ve been after its use as a pejorative. At this point, I can’t remember, and frankly, the world is probably better off forgetting.

I understand. In the earlier days of Go package management, it was pretty common for folks to compare it to Cargo. In retrospect, this was probably bad, but it did serve to highlight some pretty damning issues with Go at the time. But I feel they addressed the shortcomings significantly with Go modules, and now it has become much more a matter of taste.

I enjoy Go’s idea of trying to make source control the only source of truth, but I don’t think it’s as well-received as the more tried-and-true approach of Cargo and other centralized package repositories. I suppose time will tell.

Re: How Go mitigates supply chain attacks

#222
post #131

Earlier quoted context omitted.

As far as I understand it... the import path that you use to import a package acts as its identity, and only one version of any given package will be installed. The way that it will determine this is by choosing the lowest version specified in any package that depends on a given package. Major versions of packages are required to have different import paths with Go modules, so when depending on two different major ve…

I think you might have a small typo here: > by choosing the lowest version specified in any package that depends on a given package It picks the highest version specified in any of the requirements. (That's the minimal version that simultaneously satisfies each individual requirement, where each individual requirement is saying "I require vX.Y.Z or higher ". So if A requires Foo v1.2.3 and B requires Foo v1.2.4, v1.2…

Yep, I regrettably described the system wrong. It’s the highest version specified, and thus minimum version possible.

Re: How Go mitigates supply chain attacks

#223
post #222

Earlier quoted context omitted.

I think you might have a small typo here: > by choosing the lowest version specified in any package that depends on a given package It picks the highest version specified in any of the requirements. (That's the minimal version that simultaneously satisfies each individual requirement, where each individual requirement is saying "I require vX.Y.Z or higher ". So if A requires Foo v1.2.3 and B requires Foo v1.2.4, v1.2…

Yep, I regrettably described the system wrong. It’s the highest version specified, and thus minimum version possible .

That's a nice & concise way to describe it.

Re: How Go mitigates supply chain attacks

#224
post #199

Earlier quoted context omitted.

I might be misunderstanding GP, but I think what they're saying is that when package A depends on package B, building package A will use B's lockfile. Assuming that's the case, I think this is generally not how Rust does things, as by default Cargo.lock is explicitly listed in the .gitignore when making a library crate, although there's nothing stopping anyone from just removing that line. I think I remember reading…

> I think this is generally not how Rust does things That is correct. > as by default Cargo.lock is explicitly listed in the .gitignore when making a library crate Even if it is included in the contents of the package, Cargo will not use it for the purpose of resolution. The "don't check it in" thing is related, but not because it will be used if it's included. It's because of the opposite; that way new people who do…

Ah, good to know! I'm glad I asked

Re: How Go mitigates supply chain attacks

#225
post #222

Earlier quoted context omitted.

Yep, I regrettably described the system wrong. It’s the highest version specified, and thus minimum version possible .

That's a nice & concise way to describe it.

Minimalistic Version Selection might have been a better term for it.

That did confuse me a lot. Selecting the maximum makes a lot more sense, since that gets SemVer assumptions correct.

Re: How Go mitigates supply chain attacks

#226
post #217

Earlier quoted context omitted.

The article seemed to go out of its way not to mention any specific package manager or ecosystem. So I think comparing to Rust is completely reasonable.

It didn’t mention one by name, but Rust hasn’t been subject to any widely publicized supply chain attacks. They do, however, mention left-pad by name. I think it can be implied that they really did just mean npm.

They definitely should have said that then. Simply referring to "lockfiles" paints with a very broad brush that includes a number of package managers that don't have the problems that NPM does.

Re: How Go mitigates supply chain attacks

#227

Earlier quoted context omitted.

> You already know[0] the answer to the most of that question, so I don't know why you're asking that part again. My point is that once you start editing (either by hand or through a tool) the version numbers in the second section, then that's no longer cached state derived entirely from the go.mod files of your dependencies which can be regenerated from scratch. It contains some human-authored decisions and regenera…

> It contains some human-authored decisions and regenerating that section without care will drop information on the floor. > Maybe the answer here is that even when you ask the tool to remove unneeded transitive dependencies, it won't roll back to an earlier version of bar? So it will keep it at 1.2? I'm not aware of any package management system that will remember dependencies you no longer depend on, except by huma…

I appreciate the time you put into these comments and definitely learned a lot from them.

My original point was just that the article reads like an incorrect indictment of all other package managers that use lockfiles. Whether Go does things better is for most part orthogonal to what I was initially trying to get at.

Re: How Go mitigates supply chain attacks

#228
post #217

Earlier quoted context omitted.

It didn’t mention one by name, but Rust hasn’t been subject to any widely publicized supply chain attacks. They do, however, mention left-pad by name. I think it can be implied that they really did just mean npm.

They definitely should have said that then. Simply referring to "lockfiles" paints with a very broad brush that includes a number of package managers that don't have the problems that NPM does.

I believe Cargo does still have less strictness over dep versions than Go modules, since it will never use a module newer than the one specified in any go.mod file. Lockfiles are generally not honored recursively, and I don’t think Cargo is different here? Hope I’m not spreading misinformation, though I couldn’t find any docs with a cursory glance.

I don’t want to make assertions that I’m less sure of, but I think NPM and Cargo are actually more similar than different here. They both specify exact versions in lock files, for all nested dependencies, but don’t honor the lock files present inside dependencies, instead calculating the nested deps from the constraints.

Re: How Go mitigates supply chain attacks

#229
post #217

Earlier quoted context omitted.

It didn’t mention one by name, but Rust hasn’t been subject to any widely publicized supply chain attacks. They do, however, mention left-pad by name. I think it can be implied that they really did just mean npm.

They definitely should have said that then. Simply referring to "lockfiles" paints with a very broad brush that includes a number of package managers that don't have the problems that NPM does.

The default way Go handles go.mod is fairly different than the default way Cargo handles Cargo.lock files, including for example with libraries.

Also, when the blog says:

> Moreover, when a dependency is added with go get, its transitive dependencies are added at the version specified in the dependency’s go.mod file, not at their latest versions, thanks to Minimal version selection.

I believe that is significantly different than default Cargo behavior and for example default 'pub' behavior for Flutter (though I know approximately nothing about Flutter package management beyond a cursory search just now ;-)

To my knowledge, both Cargo and Flutter 'pub' prefer the most recent / highest allowed version by default when asked to solve constraints, whereas Go does not.

Cargo: [1]

> When multiple packages specify a dependency for a common package, the resolver attempts to ensure that they use the same version of that common package, as long as they are within a SemVer compatibility range. It also attempts to use the greatest version currently available within that compatibility range.

Flutter 'pub': [2]

> For each package in the graph, pub looks at everything that depends on it. It gathers together all of their version constraints and tries to simultaneously solve them. (Basically, it intersects their ranges.) Then it looks at the actual versions that have been released for that package and selects the best (most recent) one that meets all of those constraints.

[1]: https://doc.rust-lang.org/cargo/reference/resolver.html

[2]: https://dart.dev/tools/pub/versioning#constraint-solving

Re: How Go mitigates supply chain attacks

#230

Earlier quoted context omitted.

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.

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.
Post reply on HN