Live data from Hacker News

How Go mitigates supply chain attacks

go.dev

31–40 of 265 posts

Re: How Go mitigates supply chain attacks

#31

Go is a distillation of many decades of software engineering experience. The people behind Go (e.g., Russ Cox) have learned from history. The peanut gallery loves to complain about superficial aspects of Go. Typically these are people with little or no actual experience using the language and tools. They fixate on imagined problems that don't matter in practice. But anyone who has used Go full-time for a few years is…

For a decade+, people complained that go lacks generics. Would you say those were all people with no experience fixated on an imaginary problem that doesn't matter, or were the complaints valid?

I would say that it is legitimately annoying to have to copy and paste data structures, but mostly doesn't matter, and the intensity of the complaining does not match the intensity of the problem.

People mostly just dont like the expertise of the go devs.

Re: How Go mitigates supply chain attacks

#32
node, python, ruby...etc including go modules can lock their dependencies, Go really wins when it can be wrapped in a reasonably-sized one binary, nothing beats that in deployment, for all the others you have to pull in lots of packages into the target system

Re: How Go mitigates supply chain attacks

#33
post #28
post #19

Earlier quoted context omitted.

let foo; try { foo = await is_this_better(); } catch (err) { console.log("if err != nil doesn't seem so bad all of a sudden"); }

func ThisCouldUseExceptions() error { err := Exceptions() if err != nil { return terrors.Propagate(err) } err = GeneraliseBetter() if err != nil { return terrors.Propagate(err) } value, err = InFunctionsWithMultipleErrorPoints() if err != nil { return terrors.Propagate(err) } value, err := AlsoTheyHelp() if err != nil { return terrors.Propagate(err) } chained_val, err := WithChaining(value) err = AndPreventAccidental…

    func ThisCouldUseExceptions() error {
        err := Exceptions(arg)
        if err != nil {
            return fmt.Errorf("if a '%v' dev: %w", err)
        }
    
        err = GeneraliseBetter()
        if err != nil {
            return fmt.Errorf("has to actually: %w", err)
        }
    
        value, err = InFunctionsWithMultipleErrorPoints()
        if err != nil {
            return fmt.Errorf("read these errors: %w", err)
        }
    
        value, err := AlsoTheyHelp()
        if err != nil {
            return fmt.Errorf("they will actually be: %w", err)
        }
    
        chained_val, err := WithChaining(value)
        if err != nil {
            return fmt.Errorf("useful: %w", err)
        }
        err = AndPreventAccidentallyIgnoringErrors(chained_val)
        if err != nil {
            return fmt.Errorf("this isnt a real problem: %w", err)
        }
    }

Re: How Go mitigates supply chain attacks

#34

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

Discussing "what is a lockfile" is a bit of a headache because different languages have different files which do different things. Generally speaking, there's some file which specifies the dependency versions and some file with cryptographic checksums of the all transitive dependencies. In Go it's go.mod / go.sum. In NPM, it's package.json / package-lock.json. In Rust it's Cargo.toml / Cargo.lock. Diving into the exa…

> any new, poisoned version of libB

Conversely, you will get any old security-buggy version of libB instead.

Most package managers when adding a new dependency assume newer versions are "better" than older versions. Go's minimum version system assumes older is better than newer.

I don't think there's any clear argument you can make on first principles for which of those is actually the case. You'd probably have to do an empirical analysis of how often mailicious packages get published versus how often security bug fix versions get published. If the former is more common than the latter, then min version is likely a net positive for security. If the latter is more common than the former, then max version is probably better. You'd probably also have to evaluate the relative harm of malicious versions versus unintended security bugs.

Re: How Go mitigates supply chain attacks

#35

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

There are some subtleties here, but go.mod files are not lockfiles, including go.mod files don't follow a traditional constraint/lockfile split, which I think is part of the point in that snippet you quoted.

Another way they differ is when installing a top-level tool by default npm does not use the exact version from a library's lockfile to pick the selected version of another library as far I as understand, whereas Go does by default use the exact version required by a library's go.mod file in that scenario.

In other words, go.mod files play a bigger role for libraries than a traditional lockfile does by default for libraries in most other ecosystems.

Here's a good analysis on the contrast between go.mod and the default behavior of more traditional lockfiles (using the npm 'colors' incident as a motivating example):

https://research.swtch.com/npm-colors

That link also includes some comments on 'npm ci' and 'shrinkwrap' that I won't repeat here.

All that said, go.mod files do record precise dependency requirements and provide reproducible builds, so it's possible to draw some analogies between go.mod & lockfiles if you want. I just wouldn't say "go.mod files are lockfiles". ;-)

Re: How Go mitigates supply chain attacks

#36
post #19
post #12

Earlier quoted context omitted.

Quoted post unavailable.

let foo; try { foo = await is_this_better(); } catch (err) { console.log("if err != nil doesn't seem so bad all of a sudden"); }

Well you can actually put many exception yielding statements in the try, unlike with go where your code is full of "if err:=nil{}" after every potential error.

Most of the time when an exception occurs in sequential operations that can fail, you don't really care where it failed exactly, only that the failure was caught.

The irony is that Go does have half baked exceptions (panic,recover) on top of that error as value convention.

Re: How Go mitigates supply chain attacks

#37

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

[deleted]

Re: How Go mitigates supply chain attacks

#38

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

The author is saying that Go provides the same guarantees with just a package list in the go.mod file that other package managers need both a package list and lock file to solve.

go.sum is essentially a distributed / community maintained transparency log of published versions of packages.

Re: How Go mitigates supply chain attacks

#39
post #19

Earlier quoted context omitted.

let foo; try { foo = await is_this_better(); } catch (err) { console.log("if err != nil doesn't seem so bad all of a sudden"); }

Well you can actually put many exception yielding statements in the try, unlike with go where your code is full of "if err:=nil{}" after every potential error. Most of the time when an exception occurs in sequential operations that can fail, you don't really care where it failed exactly, only that the failure was caught. The irony is that Go does have half baked exceptions (panic,recover) on top of that error as valu…

Far easier to work with and understand when you dont need to perform a massive disruptive ceremony to handle exceptions. I've been working full time in java for the past 4 years and basically no one handles exceptions because its so cumbersome and bad to read. Not so in Go. Go does it better.

Re: How Go mitigates supply chain attacks

#40

Earlier quoted context omitted.

Discussing "what is a lockfile" is a bit of a headache because different languages have different files which do different things. Generally speaking, there's some file which specifies the dependency versions and some file with cryptographic checksums of the all transitive dependencies. In Go it's go.mod / go.sum. In NPM, it's package.json / package-lock.json. In Rust it's Cargo.toml / Cargo.lock. Diving into the exa…

> any new, poisoned version of libB Conversely, you will get any old security-buggy version of libB instead. Most package managers when adding a new dependency assume newer versions are "better" than older versions. Go's minimum version system assumes older is better than newer. I don't think there's any clear argument you can make on first principles for which of those is actually the case. You'd probably have to do…

Go just expects you to manually trigger the updates. Thats all. It still is in favor of updating to take security fixes, so i think your argument is wrong.
Post reply on HN