* joy of coding
* (human) efficiency of coding
* performance of idiomatic code
* interoperability with C
* deployability
I'm totally sold on Rust. Yet: Why would I want to replace tried and tested tools with new versions just because they're written in Rust?
I burned myself on this when I was young and naive: Having just learned Haskell, I tried to use Haskell replacements for everything. It was incredibly stupid and counterproductive (the biggest real-world pain was clinging to darcs over git for a long time at the beginning of the DVCS wars – not because of darcs' arguable good features, but because it is written in Haskell; so stupid).
* Old tools are well established, not looking for major feature additions or changes
* Hard to add new features to old C-based system tools due to mature codebase and being written in C
* Using Rust to reach a low-bug/maintainable state more quickly than a re-write in C or C++
* Adding a bunch of quality of life features that make it worth switching
The big downside with these tools, of course, is that they are re-writes of tools that have been standard Linux/Unix system tools for a long time and can be generally expected to be present on any system for the purpose of shell scripts, services etc. Using any of these tools in a shell script requires the user to install it, along with the whole dependency graph that rust typically comes with (at least when building from source which is typically the case with rust).
Nowadays the distroless movement and the general zeal towards minimizing the overhead of a Docker image have the positive side-effect of making us less reliant on the older tools. So we can opt for newer ones (although it's very hard to beat 120KB of a classic old tool to 4MB of a new Golang/Rust tool still).
As for rewriting in Rust, the main point for me is always the memory safety. When it comes to writing programs, there's a ton of very nice languages out there already.
I don't believe performance will be significantly different if you're comparing a C vs a Rust tool though.
sd is an order of magnitude faster than sed, but it's missing some features like deleting matching lines.
You could rewrite some of those older core utils written in C to make them run concurrently...
Rust and Go thus occupy a sweet spot for CLI tools, because they have the advantage of high-level maintainable code AND being fast, easily installable binary executables.
I absolutely care if the BT stack of my phone is written in a safe language, because many of the security flaws that make many, many Android devices permanently unsafe (due to end of support) are caused by memory unsafety.
On the other hand, I have the suspicion that Rust is voiced a bit too much by a loud minority - I like Rust as much as I don't like Golang, nonetheless I think that for the majority of non-performance critical projects, Golang may be a better fit.
True. But most other classes of bug are not security bugs by default in the way that memory safety bugs are.
Also half the software mentioned in that gist should never be used in security-focused applications anyway (if your depending on ‘cat’ or ‘awk’ to be bug free for your application to be hardened then you’re already doing it wrong)
An overflow bug in awk is only exploitable if someone can craft input into awk. And if you’re allowing people to do that then you’ve already given them access to remotely run code without them needing a bug.
This is how the vast majority of build systems are configured. If I have owned a dev and can push code to a branch I can likely execute code in their build environment. If they then parse that build output with something like awk, that's attack surface.
Is it the first thing I'd try to attack? Nope. But I do wonder what the cumulative impact of every binary on your system being memory safe would be. I'd definitely feel better.
But then you’re also executing that code as a trusted user. Ie the real hack is owning the dev.
> This is how the vast majority of build systems are configured.
No. The vast majority of build systems are either locked to private repositories, and/or a subset of developers, and/or run in an ephemeral sandbox.
> But I do wonder what the cumulative impact of every binary on your system being memory safe would be.
I’d already answered that. It’s negligible because if someone can exploit a buffer overflow in awk then they can already run arbitrary code in awk (remember, awk is a programming language). So if you’re not already taking precautions about who is running what on your build system and how running code is sandboxes then it’s not going to take a buffer overflow bug to RCE it.
That's like saying the real hack is sending a phishing email, ignoring all privesc, lateral movement, etc.
> No. The vast majority of build systems are either locked to private repositories, and/or a subset of developers, and/or run in an ephemeral sandbox.
I didn't say otherwise. I said that the majority allow untrusted execution. If you consider your engineers laptops to be trusted you're thinking about networks the way people did ~10+ years ago.
> It’s negligible because if someone can exploit a buffer overflow in awk then they can already run arbitrary code in awk
This isn't true, but even if it were you can just replace awk with anything else that's not turing complete.
i never said anything about trusting engineers laptops.
Let me put it another way, are you running your build pipelines bare metal, allowing anyone to instantiate the pipeline against a branch of code that anyone in the public has written? Or is that build pipeline running against a private repository, or triggered by trusted users, or does it run inside a temporary VM or container that gets destroyed afterwards? That’s where you harden CI/CD. I’m not suggesting fixing buffer overflows aren’t worthwhile (security should be multilayered after all) but it’s missing the real risk since you’ve already got code remotely executing. Thus your threat model should be about ensuring you minimise the blast radius of that code.
To use your colourful language: if your build pipelines are running bare metal then you’re thinking about infra like people did ~10 years ago.
> This isn't true, but even if it were you can just replace awk with anything else that's not turing complete.
But you’re still not addressing the real issue. If you can’t trust the the code executing and you’re not sandboxing that code then you’ve already lost the fight. You can’t give unrestricted access to execute code remotely and then moan “we wouldn’t have been exploited if everything was written in Rust”. The bone headed design was allowing unrestricted remote code execution and not the buffer overflow bug in ‘cat’.
> That's like saying the real hack is sending a phishing email, ignoring all privesc, lateral movement, etc.
It’s really not. What I’m taking about is the equivalent of saying “phishing attacks are always going to happen so you need MFA et al to harden against the array of of ways one can manipulate the system”
You’re entire security model seems to be focused around fixing every fucking executable against every possible class of bug and that’s insanely impractical. Whereas I’m suggesting one shouldn’t implicitly trust remote code in build pipelines to begin with.
The last study I saw was that 52% of security vulnerabilities were still basic memory safety vulnerabilities. Memory safety isn't the only thing, but it's still the biggest thing.
> (if your depending on ‘cat’ or ‘awk’ to be bug free for your application to be hardened then you’re already doing it wrong)
People run cat or awk on log files (where an attacker could easily craft particular data patterns) all the time. Maybe they shouldn't, but they do.
My point wasn’t that memory safety isn’t a big issue. It’s that it’s not the only cause of vulnerabilities. Assuming your 52% figure is accurate (and I’m happy to take your word on that) that still means that roughly half of all vulnerabilities are not memory safety. Which means your figure actually just reinforces my point.
> People run cat or awk on log files (where an attacker could easily craft particular data patterns) all the time. Maybe they shouldn't, but they do.
I think there’s enough obscurity there hidden from the attacker that such usage should be safe from all but the most determined of attacker. And even then, they’d likely need some other attack to probe for usage about what systems are listening to what logs and using which POSIX utils that you could argue the attacker already has the access they need without going to the pain of crafting an overflow bug in a log file.
Im not saying those bugs don’t exist nor shouldn’t be addressed, I’m just being pragmatic about their exploitability.
The bigger issue is CI/CD pipelines. Often they’re define in the same mono-repo as the source itself and they’ll have execution rights automatically because that’s literally their function as a build and test pipeline. But because said pipelines are already visible and already executable, you need to have greater controls around that pipeline to prevent abuse otherwise it’s already game over even without an overflow bug.
Sure, but that half is every other category of bug put together. I guess if your model is that every other class of bug will be significantly increased by a rewrite then maybe that logic makes sense, but that seems unlikely to me.
Try reading the thread again
And yes, I did say that at the start of the conversation. Sorry I’d forgotten about that part because this conversation had taken a tangent on discussing other specifics in security.
I do stand by my comments, a rewrite does introduce new bugs and not all security bugs are buffer overflows. Rust doesn’t protect you against bugs like Shellshock. They protect against bugs like Heartbleed. But people frequently forget about the former when focusing on the latter. So absolutely we need to be considered when replacing battle tested software with an entirely new code. It’s not an unfair meme when people state this. If it were an easy and risk free upgrade then we’d have already done so in one of the other safer languages that predate Rust. A lot of what’s changed between then and now isn’t that languages have gotten better, it’s simply that Rust is trendier than any of the safer languages before them. And that’s a pretty awful reason to reason to rush a complete rewrite of the entire stack.
Source: I’m an old fart who’s been writing safe code in safe languages for 30+ years.
"Try reading the thread again" is extremely condescending.
> Rust doesn’t protect you against bugs like Shellshock. They protect against bugs like Heartbleed. But people frequently forget about the former when focusing on the latter. So absolutely we need to be considered when replacing battle tested software with an entirely new code. It’s not an unfair meme when people state this.
Like I said, over half of security bugs are the kind of bug that Rust protects you against, whereas the other half (apparently more like a quarter, per side thread) is every other category of bug put together. So unless your model is that every other category of bug will be significantly increased by a rewrite, the rewrite wins out on net.
> If it were an easy and risk free upgrade then we’d have already done so in one of the other safer languages that predate Rust. A lot of what’s changed between then and now isn’t that languages have gotten better, it’s simply that Rust is trendier than any of the safer languages before them.
Per another side thread, I do agree that the reason people are rewriting in Rust now when they weren't rewriting in OCaml 10 years ago is mostly trendiness. But I disagree about which of those two decisions is the mistake.
Rewrite does increase other types of bugs though. But the more specific point I’m making is that the domain matters massively here. A buffer overflow bug in ‘cat’ isn’t equivalent to a buffer overflow bug in ‘openssh’. If you’re worried about RCEs in ‘cat’ then the fix isn’t to rewrite ‘cat’, it’s to fix the calling pipeline. Eg is the containerisation service secure? Using Rust as a blunt hammer to fix all security bugs demonstrates a real lack understanding about how to build hardened systems in the first place.
This is the point I’m making. Not that Rust shouldn’t be used as part of the solution but rather that people need to stop bleating on about Rust being “the” solution. People love to quote vulnerabilities in Chrome and OpenSSL as a reason everything should be rewritten in Rust but fail to understand that coreutils are called in entitled different circumstances and thus have an entirely different security model.
By the way, your blog link needs updating in your HN profile (to github.io). Some really interesting content on there and I really enjoyed your writing style too. Thanks for publishing your thoughts :)
Don’t get me wrong, I’m all for writing stuff in safer languages (I personally haven’t touched C in years for that reason). But simply throwing Rust at the problem without assessing the risks is just as careless. In the case of most POSIX base utils, the risk isn’t buffer overflows, it’s people exposing internal tools to untrusted external users.
Take shellshock for example, that’s a prime example for just how careless people can be. And while there was patches to fix that vulnerability in Bash, people shouldn’t have been writing software that passed untrusted data to Bash in the first bloody place.
My point is: Security is a multi-layered problem. So by all means let’s pivot towards newer, safer, languages of it can remove an entire class of bugs. But let’s not pretend that rewriting the entire of POSIX in Rust is either practical nor the end of the discussion. And if we acknowledge it’s not, then we must also acknowledge there’s already things we can do to harden against our C++ utils today while those C++ utils are still a necessity.
This is why the Rust argument fucks me off. People expect too much from it and use it as an argument whenever other countermeasures should have been in place irrespective of the vulnerability that was inevitably used.
As for other kinds of bugs, yeah, that's inevitable, but I still prefer to have the memory safety bugs eliminated from the get go so I'd still say it's a worthy sacrifice to walk the road to safe tools one more time just for the memory safety.
So yeah, no need to rewrite tools in already memory safe languages but when it comes to C/C++ tools then yes, we need to rewrite them.
Sure that given enough resources, motivation and time, Anything is possible. But new code means bugs and uncertainty.
Some of the tools listed are not small if a one for one replacement is the target. Vim is listed??
How long before these tools are considered as matured and ready for production?
This is changing, happily, but OCaml I always viewed as kind of an elitistic intellectuals club. Happy to be proven more and more wrong lately, though!
I am looking forward, eagerly, to OCaml 5.0 and having an amazingly fast compiler with solid multicore runtime system support! It's very likely I might abandon Rust for OCaml when that time comes (8 - 12 months).
Instead, I think it comes from the fact that when it was first developed in the 90s, it was viewed in the context of C (and this attitude has carried over somewhat to the modern day where it makes much less sense). For example, building non-trivial projects with just the compiler is very painful from most modern perspectives, but it's very similar to what you have to do for C.
What you say is fair. It seems that OCaml's niche with time moved from competing with C to competing with Haskell and Rust -- at least from where I am standing. Maybe some members of the community aren't OK with that goalpost moving. That would be understandable.
But to be fair, I like OCaml more than Rust but I got very spoiled by both Elixir's and Rust's tooling -- both are excellent enablers of productivity.
Once OCaml overcomes this barrier (and introduces multicore) I am definitely going in, neck deep! :)
Another factor is that creating a language (Rust, Go etc.) from scratch lets you have nice unified tooling to an extent that is probably just not possible with languages with baggage. So I doubt OCaml will ever manage to be quite as seamless as those, but IMO it's already gone from significantly worse tooling than e.g. Python/Java to significantly better, and is still improving all the time!
I could not care less about the hype squad screaming endlessly about every single side project that is written in Rust because of the sake of the language. If it is useful and it makes me money then fine, other than that I ignore it.
If the tool that is being developed doesn't help me make money, then I do not care or I won't use it.
As for choosing the best programming language? I do not care unless it is the one that makes me the most money. in some use cases, it is definitely not Rust.
This is Hacker news. It's news for people who want to fuck around with tech.
Yet this site seems to be hosted by a company whose goal is purely about making money by investing in companies they find which are likely to give huge returns. i.e A VC fund.
So rewriting it in Rust for the sake of Rust is irrelevant to them and doesn't give any advantage whatsoever and won't get their attention.