Live data from Hacker News

How Go mitigates supply chain attacks

go.dev

141–150 of 265 posts

Re: How Go mitigates supply chain attacks

#141

Earlier quoted context omitted.

Good question! The thing that the standard library has that I don't is version aggregation . The problem is not publishing under a single domain, the problem is publishing under a single version . Publishing a bunch of packages that I claim are high quality doesn't help users decide which versions to use, they still have to make this decision on a package-by-package basis. Note that I may be in the middle of a big re…

You could sort of do that using a Go module that points to all your other modules. Then anyone who depends on that will get the versions you specify (at a minimum). But a problem is that they would also download all the modules you point at, whether they use them or not. To fix that, the package system would need a "soft dependency" where, if a module exists, it must be at least the version indicated.

Good idea with "soft dependencies". You'd also need to make the go.mod RequireSpec version argument [1] optional so it can be overridden by the module group.

    require example.com/my-module-group 1.2.3
    require example.com/some/module // selects minimum version specified by my-module-group
[1]: https://go.dev/ref/mod#go-mod-file-require

I also noticed Workspaces [2] which I hadn't seen before. They look interesting, but appear to exist for a different purpose. Maybe workspaces with a bunch of replace directives & some cli tooling could emulate a system like what is described here.

[2]: https://go.dev/ref/mod#workspaces

Re: How Go mitigates supply chain attacks

#142
post #83

Earlier quoted context omitted.

>Sure, your problem with Java is also a social issue that has nothing to do with the language. Quoting myself: "This is a social problem, influenced by language design." >This isn't Java's "culture" to not handle errors at all. Go's conventions imposed in its std libs are certainly not a superior model by any measure as I previously showed. This is java's culture, and I assert it from experience. It is a result of th…

Having worked on golang code bases for several years now, I assure you it's not a theoretical problem. It's not fun to have ignored or overwritten errors that keep the program going as if nothing is happening.

If you overwrite or ignore your variables you're going to have a bad time. Period. That's not unique to errors. I'm not sure you've said anything to convince us that making mistakes around errors alone is anything more than theoretical.

Beyond defining an interface named error (early versions didn't even offer that), Go does not have a concept of errors, so I'm not sure it is even possible for there to be a problem specific to errors. Certainly Go could do more to help you with correctness in general.

Re: How Go mitigates supply chain attacks

#143

Earlier quoted context omitted.

It's not a URL, it's just an identifier that sort-of resembles a URL similar to Kubernetes annotation conventions.

It may not be quite a URL, but it contains the URL. It definitely more than just "sort-of resembles a URL". See how the module path to URL lookup is done here: https://go.dev/ref/mod#vcs-find

I understand your meaning, but that link supports my claims. The package path helps the Go tool infer the actual URL, but it doesn't contain the URL itself (e.g., the actual URL has a scheme/protocol component and potentially a `go-get=1` query string argument which don't exist as part of the path). This is what I meant when I said it "sort-of resembles a URL", but I understand from this conversation how that wording wasn't clear.

Re: How Go mitigates supply chain attacks

#144
post #81

The elephant in the room here is NPM, and I think the obvious problem there is the culture. I have a tiny app I've been playing with using create-react-app. There are over 800 directories in node_modules. That absolutely dwarfs the number of any other language I've used. Even in a medium sized rails app, you likely have some awareness of what every dependency is. It's just impossible with npm. One thought I've had to…

I think the NPM organization is completely aware just how dangerous this all is, and is eager to hide it. For example, if you look up an NPM package, it'll list its direct dependencies. But, there's no acknowledgement whatsoever of all the stuff that comes along for the ride. I'd love to have a well-supported ranking of NPM packages in terms of their dependencies (and their dependencies' dependencies, etc). Knowing t…

I agree that it would be nice for NPM to show the total footprint of a module, especially if that provides some social incentive to reduce the dependency count.

Re: How Go mitigates supply chain attacks

#145

Earlier quoted context omitted.

It may not be quite a URL, but it contains the URL. It definitely more than just "sort-of resembles a URL". See how the module path to URL lookup is done here: https://go.dev/ref/mod#vcs-find

I understand your meaning, but that link supports my claims. The package path helps the Go tool infer the actual URL, but it doesn't contain the URL itself (e.g., the actual URL has a scheme/protocol component and potentially a `go-get=1` query string argument which don't exist as part of the path). This is what I meant when I said it "sort-of resembles a URL", but I understand from this conversation how that wording…

Fair. Strictly speaking it doesn't even "contain" a URL. But I think in the context of this conversation it acts like a URL -- it allows the Go tooling to fetch code from an arbitrary domain and path on the internet.

Re: How Go mitigates supply chain attacks

#146
post #86
post #23

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

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…

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.

Re: How Go mitigates supply chain attacks

#147

Earlier quoted context omitted.

FWIW, that's not what Go does. In your scenario, a Go binary ends up with a single copy of library X -- the 1.0.1 version. That's because library A is stating "I require at least v1.0.0 of X", and library B is stating "I require at least v1.0.1 of X". The minimal version that satisfies both of those requirements is v1.0.1, and that's what ends up in the binary. That behavior is Go's "Minimal Version Selection" or "MV…

how are you not describing package.json right now what is the difference

The difference is the npm ecosystem actively encourages automatically following SemVer because by default it uses a ^ to prefix the version number. https://heynode.com/tutorial/how-use-semantic-versioning-npm...

The practice of dependencies’ dependencies being specified using SemVer version constraints to auto-accept minor or patch changes is the difference compared to Go, and why lockfiles will not always save you in the npm ecosystem. That said, approaches like Yarn zero-install can make very explicit the versions installed because they are distributed with the source. Similarly, the default of using npm install is bad because it will update lockfiles, you have to use npm ci or npm install —ci both of which are less well-known.

So it’s not impossible to fix, just a bad choice of defaults for an ecosystem of packages that has security implications about the same as updating your Go (or JS) dependencies automatically and not checking the changes first as part of code review. Blindly following SemVer to update dependencies is bad, from a security perspective, regardless of why or how you’re doing it.

Re: How Go mitigates supply chain attacks

#148

Earlier quoted context omitted.

FWIW, there are two machine-formatted sections of go.mod -- the first for direct dependencies, the second section for indirect dependencies. (That's as of Go 1.17. Previously, that information was communicated via machine-generated comments in a single section).

That seems reasonable. I think I personally lean towards keeping them in separate files entirely because I like a clearer separation between human-authored content and machine-derived state.

but if you ever bump up the version of an indirect dependency (maybe to pick up a bugfix earlier), is this now a direct or indirect dependency?

Re: How Go mitigates supply chain attacks

#149
post #70

> There is no way for changes in the outside world—such as a new version of a dependency being published—to automatically affect a Go build. > Unlike most other package managers files, Go modules don’t have a separate list of constraints and a lock file pinning specific versions. The version of every dependency contributing to any Go build is fully determined by the go.mod file of the main module. I don't know if thi…

It’s very subtle, but there are some important differences. For example, lockfiles are not recursive in NPM: the NPM package (usually?) does not contain the lockfile and does not adhere to it when installed as a dependency. It will pick the newest version of dependencies that matches the spec in package.json. Go mod files are used recursively, and rather than try to pick the newest possible version, it will go with t…

This really depends on the specific package manager: if you're building an application in Rust, its lockfile will contain the full tree of dependencies, locked to a specific version.

Re: How Go mitigates supply chain attacks

#150
post #80
post #23

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

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

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.

Post reply on HN