5 ms·
> Why would statically linking a library reduce the number of vulnerabilities in it? I use pure go implementations only, and that implies that there's no stati
by cookiengineer 9mo ago
> Why would statically linking a library reduce the number of vulnerabilities in it?
I use pure go implementations only, and that implies that there's no statically linked C ABI in my binaries. That's what disabling CGO means.
- akoboldfrying 9mo agoWhat I mean is: There will be bugs* in that pure Go implementation, and static linking means you're baking them in forever. Why is this preferable to dynamic linking? * It's likely that C implementations will have bugs related to dynamic memory allocation that are absent from the Go implementation, because Go is GCed while C is not. But it would be very surprising if there were no bugs at all in the Go implementation.
- tptacek 9mo agoThey're prioritizing memory corruption vulnerabilities, is the point of going to extremes to ensure there's no compiled C in their binaries.
- underdeserver 9mo agoYou can have memory corruption in pure Go code, too.
- tptacek 9mo agoUh huh. That's where all the Go memory corruption vulnerabilities come from!
- cookiengineer 9mo agoNobody claimed otherwise. You're interacting with a kernel that invented its own programming language based on macros, after all, instead of relying on a compiler for that. What could go wrong with this, right? /s
- staticassertion 9mo agoAnd in Rust (yes, safe Rust can have memory safety vulnerabilities). Who cares? They basically don't happen in practice.
- cookiengineer 9mo agoIt would be nice if there was something similar to the ebpf verifier, but for static C, so that loop mistakes, out of boundary mistakes and avoidable satisfiability problems are caught right in the compile step. The reason I'm so avoidant to using C libraries at all cost is that the ecosystem doesn't prioritize maintenance or other forms of code quality in its distribution. If you have to go to great lengths of having e.g. header only libraries, then what's the point of using C99/C++ at all? Back when conan came out I had hopes for it, but meanwhile I gave up on the ecosystem. Don't get me wrong, Rust is great for its use cases, too. I just chose the mutex hell as a personal preference over the wrapping hell.
- supriyo-biswas 9mo agoI believe this is fil-c[1]. [1] https://fil-c.org/ https://fil-c.org/
- saagarjha 9mo agoWhat do you consider to be a loop mistake?
- cookiengineer 9mo agoEverything that is a "too clever" state management in an iterative loop. Examples that come to mind: queues that are manipulated inside a loop, slice calls that forget to do length-- of the variable they set in the begin statement, char arrays that are overflowing because the loop doesn't check the length at the correct position in the code, conditions that are re-set inside the loop, like a min/max boundary that is set by an outer loop. This kind of stuff. I guess you could argue these are memory safety issues. I've seen so crappy loop statements that the devs didn't bother to test it because they still believed they were "smart code", even after sending the devs a PoC that exploited their naive parser assumptions. In Go I try to write clear, concise and "dumb" code so that a future me can still read it after years of not touching it. That's what I understand under Go's maintainability idiom, I suppose.
- jerf 9mo agoAbout a year ago I had some code I had been working on for about a year subject to a pretty heavy-duty security review by a reputable review company. When they asked what language I implemented it in and I told them "Go", they joked that half their job was done right there. While Go isn't perfect and you can certainly write some logic bugs that sufficiently clever use of a more strongly-typed language might let you avoid (though don't underestimate what sufficiently clever use of what Go already has can do for you either when wielded with skill), it has a number of characteristics that keep it somewhat safer than a lot of other languages. First, it's memory safe in general, which obviously out of the gate helps a lot. You can argue about some super, super fringe cases with unprotected concurrent access to maps, but you're still definitely talking about something on the order of .1% to .01% of the surface area of C. Next, many of the things that people complain about Go on Hacker News actually contribute to general safety in the code. One of the biggest ones is that it lacks any ability to take an string and simply convert it to a type, which has been the source of catastrophic vulnerabilities in Ruby [1] and Java (Log4Shell), among others. While I use this general technique quite frequently, you have to build your own mechanism for it (not a big deal, we're talking ~50 lines of code or so tops) and that mechanism won't be able to use any class (using general terminology, Go doesn't have "classes" but user-defined types fill in here) that wasn't explicitly registered, which sharply contains the blast radius of any exploit. Plus a lot of the exploits come from excessively clever encoding of the class names; generally when I simply name them and simply do a single lookup in a single map there isn't a lot of exploit wiggle room. In general though it lacks a lot of the features that get people in trouble that aren't related to memory unsafety. Dynamic languages as a class start out behind the eight-ball on this front because all that dynamicness makes it difficult to tell exactly what some code might do with some input; goodness help you if there's a path to the local equivalent of "eval". Go isn't entirely unique in this. Rust largely shares the same characteristics, there's some others that may qualify. But some other languages you might expect to don't; for instance, at least until recently Java had a serious problem with being able to get references to arbitrary classes via strings, leading to Log4Shell, even though Java is a static language. (I believe they've fixed that since then but a lot of code still has to have the flag to flip that feature back on because they depend on it in some fundamental libraries quite often.) Go turns out to be a relatively safe security language to write in compared to the landscape of general programming languages in common use. I add "in common use" and highlight it here because I don't think it's anywhere near optimal in the general landscape of languages that exist, nor the landscape of languages that ought to exist and don't yet. For instance in the latter case I'd expect capabilities to be built in to the lowest layer of a language, which would further do great, great damage to the ability to exploit such code. However no such language is in common use at this time. Pragmatically when I need to write something very secure today, Go is surprisingly high on my short list; theoretically I'm quite dissatisfied. [1]: https://blog.trailofbits.com/2025/08/20/marshal-madness-a-brief-history-of-ruby-deserialization-exploits/ https://blog.trailofbits.com/2025/08/20/marshal-madness-a-br...