The premise of this conversation is flawed: A language isn't "insecure" or "secure." It's placed at a certain point in a safety spectrum ranging from "Do anything with no safety" to "Safely heat the room and achieve nothing."
What I'm saying is not that you can't write software that can be abused in memory-safe languages. I'm saying that you're much less likely to have extremely serious code execution vulnerabilities if you write a program in Go instead of C.
> What I'm saying is not that you can't write software that can be abused in memory-safe languages. I'm saying that you're much less likely to have extremely serious code execution vulnerabilities if you write a program in Go instead of C.
What I'm saying is that "much" less likely is overstating the difference. Most bugs in C programs are not buffer overruns, and even the ones that are would still be bugs in Go or Rust, they would just be a different kind of bug which is still plausibly exploitable under real conditions.
This is not a silver bullet kind of situation. "Rewrite everything in Go" is not actually a fix -- it's replacing code with 30 years worth of bug reports and vulnerability testing with completely untested new code, at the cost of significant resources that could better be used to fix the remaining vulnerabilities.
I'm not even saying that all the existing code is perfect. Replacing OpenSSL with entirely new code would probably do more good than harm just because the existing code is so ugly. But that's the exception rather than the rule.
There are a ridiculous number of serious vulnerabilities in C code related to lack of bounds checking and manual memory management. This isn't really opinion so much as fact. I understand what you're saying, but you're also downplaying the seriousness of C bugs relative to <most other languages> bugs.
> Most bugs in C programs are not buffer overruns, and even the ones that are would still be bugs in Go or Rust, they would just be a different kind of bug which is still plausibly exploitable under real conditions.
I don't follow. What's the equivalent of forgetting to check the length of an input string before chugging it into a too-small array in Go?
> "Rewrite everything in Go" is not actually a fix
I never said that, though. I'm not suggesting we rewrite the GNU tools in Go. But if you were to write the GNU tools from scratch today, C would be a bad choice simply because it's so easy to slip up with devastating effects, and there aren't many advantages to using it for simple tools like 'strings'.
> There are a ridiculous number of serious vulnerabilities in C code related to lack of bounds checking and manual memory management. This isn't really opinion so much as fact. I understand what you're saying, but you're also downplaying the seriousness of C bugs relative to <most other languages> bugs.
I feel like "<most other languages> bugs" tend to get ignored because it's not popular to blame <language> for bugs unless <language> is C. For example an enormous number of high severity CVEs are SQL injection but I never hear anybody saying we should replace SQL with a binary interface that clearly distinguishes statements from data, even though that would make more difference in practice than replacing C with something else.
> I don't follow. What's the equivalent of forgetting to check the length of an input string before chugging it into a too-small array in Go?
In Go the program terminates, which is at best a denial of service vulnerability. If the program is anything in the nature of Fail2ban then just causing it to die is a serious problem. Meanwhile when it restarts it will have to somehow deal with whatever corrupted state the crash left behind, which depending on the context can provide the attacker with opportunities to do arbitrarily bad things by manipulating the state to be something the programmer never anticipated. Being able to induce a restart is a huge increase in attack surface.
Immediate program termination is the "take cyanide capsule" solution to serious bugs. It may be better than some of the alternatives but it's still very bad.
> For example an enormous number of high severity CVEs are SQL injection but I never hear anybody saying we should replace SQL with a binary interface that clearly distinguishes statements from data, even though that would make more difference in practice than replacing C with something else.
Using bind parameters instead of putting data directly in queries + escaping has been standard for a long time now. That is, instead of saying "make sure to escape everything", like "make sure to avoid any bugs in C code", we indeed prefer to switch to a technique which which doesn't act pathologically in the presence of small errors. In SQL's case it doesn't require replacing the whole language. It technically doesn't have to in C, either - you could have bounds checked C - but I guess once you give up the absolute-maximum-performance goal, people prefer to use different languages.
edit: Also, while program termination is not ideal, in many cases, such as this one (strings), it is basically a non-problem, and at worst, denial of service is still loads better than arbitrary code execution.
> I feel like "<most other languages> bugs" tend to get ignored because it's not popular to blame <language> for bugs unless <language> is C. For example an enormous number of high severity CVEs are SQL injection but I never hear anybody saying we should replace SQL with a binary interface that clearly distinguishes statements from data, even though that would make more difference in practice than replacing C with something else.
I don't even use SQL, but I've heard a similar mantra plenty enough times to internalize it.
This is an API level change, not a protocol level change - but an API change is the correct answer anyways. If you change the protocol and slap an API like the SQL injection prone ones on top of it, you'll have the same vulnerabilities no matter what the protocol.
For bonus points, use static analysis to catch and forbid query strings that can't be trivially proven static.
> For example an enormous number of high severity CVEs are SQL injection but I never hear anybody saying we should replace SQL with a binary interface that clearly distinguishes statements from data, even though that would make more difference in practice than replacing C with something else.
I see 3x more memory corruption CVEs alone, than SQLI CVEs. I'm not convinced that replacing SQL (or SQL APIs) would be higher impact than replacing C and C++. And since I actually use C and C++ in my daily bread and butter, they're significantly more relevant to me.
But SQLI may be significantly more relevant to you. If that's the case, by all means, focus on them more.
> If the program is anything in the nature of Fail2ban then just causing it to die is a serious problem
If that causes a serious problem, then the architecture is bad and unsuitable for solving that problem (remember: programs can also die because of OOM conditions, flakey hardware, admin errors. If this leaves a gaping security hole open for an attacker, or lead to DoS, then you need a better approach; fail2ban functionality should be in the process handling logins for example, not a separate entity watching logfiles, which might be broken too).
> Being able to induce a restart is a huge increase in attack surface.
Compared to what? Certainly not C code, where very common issues are easily exploitable for arbitrary code execution.
Because I am sure if had ported bash to Go, you would still have the same issue with the broken parser. I am not sure if you would still have had heart bleed, but I know you wouldn't have had heart bleed if the openssl people had used the platform libc, instead of rolling their own, so I wouldn't consider heart bleed an issue with C, but an issue with the programmer.
What I'm saying is not that you can't write software that can be abused in memory-safe languages. I'm saying that you're much less likely to have extremely serious code execution vulnerabilities if you write a program in Go instead of C.