Comment by TheDong

Comment by TheDong 9 days ago

2 replies

My own experience is that the Go stdlib has resulted in worse security than, for example, rust.

The reason for that is that both the Rust and Go stdlib have a stability promise, so anything built into them can't change if it's insecure.

For example, the 'tar' package in go by default returns unsanitized paths, and has led to a bunch of CVEs: https://github.com/golang/go/issues/55356

The go stdlib can't change the tar package to make it secure by default because it would be a breaking change to do so.

Rust, on the other hand, has a tar package outside of the stdlib, and so it can evolve to be more secure and over time find a better interface.

We've seen that with various other packages, where the Go stdlib HTTP implementation defaults to no timeouts, and thus makes it easy to DoS yourself. Ditto for tcp. The tls package has similar backwards compatibility warts that make it less secure by default.

Forcing backwards compatibility with network protocols by baking them into the stdlib has largely not been a security win in my experience.

You can argue that people can build packages outside of the Go stdlib too, like if the stdlib "image/draw" package is so bad it can't be used, they can make "golang.org/x/image/draw", or if the stdlib crypto package is bad, they can make "golang.org/x/crypto"... and they did, but people still reach for the stdlib because it's easier to, which makes it an active security trap.

tptacek 8 days ago

No, I'm not going to give Rust security credit for vulnerabilities it avoided in library functionality that it simply didn't provide.

  • TheDong 8 days ago

    I'm not giving rust credit, I'm giving Go a demerit for having a large stdlib which it does not have a good path to evolve around security problems.

    We do have stuff like `golang.org/x/<etc>` and `rand/v2`, both of which people don't really use, which are I think clear indications that the go team screwed up here.

    Things like tls and http should have been separately versioned packages from the beginning, allowing infrequent breaking changes, and for users to update at their own pace independently of the compiler version.

    As-is, every time I update the go compiler, I also have to worry about setting a bunch of new GODEBUG flags (like 'x509sha1=1') to perform the compiler update without breaking stuff, and then separately deal with the breakages associated with those flags. Practically every go version in recent memory has had a breaking http or tls change which has caused issues for me.

    But of course they're all tied together, so to get a CVE fix in one package, I have to update the entire stdlib at once, so I have to accept some broken http change in order to fix a tls CVE or whatever.

    If tls were a separate package, I could update it separately from the compiler and http package and consume security updates more quickly, and also actually update my go compiler version without worrying about how much of my code will break.

    As I said, I'm not giving rust extra-credit, it did the reasonable normal thing of saying "the stdlib is for stuff we're pretty sure is actually stable", while go instead said "idk, will net.Dial ever need a timeout? Who knows, let's promise it's stable forever anyways" and "the default zero value for tls version should be 1.0 forever right", which I think deserves an obvious demerit.