Live data from Hacker News

How Go mitigates supply chain attacks

go.dev

231–240 of 265 posts

Re: How Go mitigates supply chain attacks

#231

Earlier quoted context omitted.

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 di…

[deleted]

Re: How Go mitigates supply chain attacks

#232
post #155

Earlier quoted context omitted.

> Its my entire company, and its with the open source ecosystem. Its naive to think that language constructs dont influence dev's decisions. You need to make it easy to do the right thing, not hard, and go makes it easy, which java fails at. Go makes it pretty easy to ignore errors, it's even worse than Java. An uncaught managed exception will not compile, and an uncaught unmanaged exception might terminate your prog…

> An uncaught managed exception will not compile, and an uncaught unmanaged exception might terminate your program. While it's nice that uncaught exceptions stop the program from continuing with invalid state, it'd be strictly better to not have them in the first place. That's what languages with explicit error returns provide - can't have uncaught errors if you're forced to explicitly deal with every possible error.…

> This is a deliberate decision to ignore the error - the programmer needed to explicitly type this out. As such, it's not a problem at all. Even if it was, writing a linter to detect it would be trivial.

So is not handling Java exceptions is deliberate, and again, Java forces you to handle managed exceptions.

> While it's nice that uncaught exceptions stop the program from continuing with invalid state, it'd be strictly better to not have them in the first place. That's what languages with explicit error returns provide - can't have uncaught errors if you're forced to explicitly deal with every possible error. The resulting software is way more robust that way.

Errors as value in Go are purely a convention, nothing precludes you from doing the exact same thing in Java, or JavaScript or any other possible language that has exceptions. Furthermore, Go has (stupid) exceptions, it's called panics.

Re: How Go mitigates supply chain attacks

#233

Earlier quoted context omitted.

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 di…

In that same section, the blog describes the behavior of 'go install foo@latest' and contrasts it to how the default install "in some ecosystems bypass pinning."

That is also a difference in default behavior between Go and Cargo.

To install a 'foo' binary, 'go install foo@latest' gives you the latest version of foo, but the direct and indirect dependencies used are the versions listed in foo's go.mod or a dependency’s go.mod file (and not whatever the latest versions of those direct and indirect dependencies might be at the moment the install is invoked).

'cargo install foo' supports the optional --locked flag, but its not the default behavior: [1]

> By default, the Cargo.lock file that is included with the package will be ignored. This means that Cargo will recompute which versions of dependencies to use, possibly using newer versions that have been released since the package was published. The --locked flag can be used to force Cargo to use the packaged Cargo.lock file if it is available.

There are definitely pros and cons here, but to my knowledge it is not "just NPM" that is being contrasted in the blog.

Finally, I'm no world-class Rust expert, but I like using Cargo. I think Cargo is a fantastic tool that set the bar for package mangers, and it has done great things for the Rust community. But it is easier for communities to learn from each other with a base understanding of where & why different choices have been made, which is part of what is behind some of my comments around Go's behavior. ;-)

[1]: https://doc.rust-lang.org/cargo/commands/cargo-install.html

Re: How Go mitigates supply chain attacks

#234
post #228

Earlier quoted context omitted.

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 NP…

Cargo does not do "recursive lockfiles", that's correct.

Re: How Go mitigates supply chain attacks

#235

Earlier quoted context omitted.

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 di…

In that same section, the blog describes the behavior of 'go install foo@latest' and contrasts it to how the default install "in some ecosystems bypass pinning." That is also a difference in default behavior between Go and Cargo. To install a 'foo' binary, 'go install foo@latest' gives you the latest version of foo , but the direct and indirect dependencies used are the versions listed in foo's go.mod or a dependency…

So, I believe that you're confusing two different cases here.

`cargo install` is not how you add a dependency, it's not like `npm install`. `cargo install` downloads the source for and installs a runnable binary program, like `npm install -g`. Cargo does not currently have an "add this dependency to my Cargo.toml" command built-in, but `cargo add` is coming from this purpose.

With `cargo install`, the default behavior is to completely recompute the dependency tree before doing the build. The `--locked` flag modifies that to use the lockfile included in the package to do that build instead (and in fact fail compilation if it does not exist). That lockfile will still be a full graph of all dependencies and transitive dependencies to build the binary, it doesn't like, recurse or use any lockfiles that exist in any of the dependencies' packages.

Re: How Go mitigates supply chain attacks

#236

Earlier quoted context omitted.

In that same section, the blog describes the behavior of 'go install foo@latest' and contrasts it to how the default install "in some ecosystems bypass pinning." That is also a difference in default behavior between Go and Cargo. To install a 'foo' binary, 'go install foo@latest' gives you the latest version of foo , but the direct and indirect dependencies used are the versions listed in foo's go.mod or a dependency…

So, I believe that you're confusing two different cases here. `cargo install` is not how you add a dependency, it's not like `npm install`. `cargo install` downloads the source for and installs a runnable binary program, like `npm install -g`. Cargo does not currently have an "add this dependency to my Cargo.toml" command built-in, but `cargo add` is coming from this purpose. With `cargo install`, the default behavio…

Hi Steve, first, thanks for weighing in here!

I might have misunderstood your comment, but in my GP comment I was indeed attempting to contrast 'go install foo@latest' with 'cargo install foo', which both install binaries. (I wasn't talking about 'go get bar@latest', which now is just for updating or adding dependencies to a project).

Also, I'm contrasting what happens by default at the moment either binary install command is run. My understanding is Cargo's (non-default) 'cargo install --locked foo' behavior is similar to the default behavior of 'go install foo@latest'. In other words, the default behavior is fairly different between 'cargo install foo' (without --locked) vs. 'go install foo@latest'.

I edited my GP comment to simplify the example to use 'foo' in both cases. Maybe that helps?

Re: How Go mitigates supply chain attacks

#237

Earlier quoted context omitted.

So, I believe that you're confusing two different cases here. `cargo install` is not how you add a dependency, it's not like `npm install`. `cargo install` downloads the source for and installs a runnable binary program, like `npm install -g`. Cargo does not currently have an "add this dependency to my Cargo.toml" command built-in, but `cargo add` is coming from this purpose. With `cargo install`, the default behavio…

Hi Steve, first, thanks for weighing in here! I might have misunderstood your comment, but in my GP comment I was indeed attempting to contrast 'go install foo@latest' with 'cargo install foo', which both install binaries. (I wasn't talking about 'go get bar@latest', which now is just for updating or adding dependencies to a project). Also, I'm contrasting what happens by default at the moment either binary install c…

Ah yes, I did miss that, thank you / sorry :) Too many sub-threads around here!

I don't know go install's semantics well enough to know if that comparison is true or not, I'm just trying to make sure that Cargo's semantics are clear :)

Re: How Go mitigates supply chain attacks

#238

Earlier quoted context omitted.

But if its a manual explicit choice, that adds more friction to these patches, and many developers may not update them at all. It's a trade off

A manual choice can be easily automated; an automatic choice can be difficult-to-impossible to de-automate.

It is trivial to manually upgrade dependencies in NPM. You just use `npm update ` with an optional version number if you want. And upgrading all dependencies of a Go package is also a single command. So honestly it seems like there is very little difference. My main point here is the trade-off. Either you reduce the friction for upgrades, and run the risk of malicious upgrades like node-ipc. Or you increase the friction, and run the risk of security vulnerabilities being unpatched in many projects.

I personally prefer the former. Encourage upgrades, but then NPM should also have a separate repository for community verified / trusted packages to reduce the chance of a random single developer damaging the entire ecosystem (left-pad, node-ipc, etc)

Re: How Go mitigates supply chain attacks

#239

Earlier quoted context omitted.

A manual choice can be easily automated; an automatic choice can be difficult-to-impossible to de-automate.

It is trivial to manually upgrade dependencies in NPM. You just use `npm update ` with an optional version number if you want. And upgrading all dependencies of a Go package is also a single command. So honestly it seems like there is very little difference. My main point here is the trade-off. Either you reduce the friction for upgrades, and run the risk of malicious upgrades like node-ipc. Or you increase the frict…

If I set up a new Node project I get the highest 'supported' version of whatever. If I add a new dependency I get the latest version of any transitive dependency I didn't already have. As far as I know that's impossible to disable. That's the automated upgrade I mean.

Re: How Go mitigates supply chain attacks

#240
I feel like everyone is beating around the bush here: NPM is a garbage fire, from the interface to the tooling implementation to the theory to the governance. We can talk at each other back and forth about theoretical benefits, and "friction" vs. "usability" or whatever, but NPM has been and continues to be an unmitigated security disaster. The module proxy could have a package takeover a month for the next three years and still not even come close to the ridiculous shit that has happened on NPM.
Post reply on HN