Here I go again writing about Unsafe Rust. Turns out that today I received a pingback to my article Actix-web is dead (about unsafe Rust) from Rust is a hard way to make a web API blog post. It also was featured in r/Rust reddit community! (Strangely, the post in reddit goes to the original author’s blog: Rust is a hard way to make a web API)
There, Tom wrote the following piece referring to my post:
Heck, if you ask some people, Rust is less secure than a GC’ed language for web apps if you use any crates that havehttps://macwright.com/2021/01/15/rust.html
unsafecode – which includes Actix, the most popular web framework, because unsafe code allows things like deferencing raw pointers.
It seems that there was a bit of a misunderstanding, because I don’t agree with this wording at all. If I would fix it to match better what I intended to say, I would write instead: “Rust is less secure than a GC’ed language for web apps if you use any crates that abuse unsafe code”.
But still this is overly simplistic, and it’s hard to put it in few words.
Let me try to summarize. About unsafe:
- All Rust programs depend at some level on unsafe code. It’s near to impossible to get rid of it, as it is one of the basic building blocks of Rust. The standard library uses a lot of unsafe code (in small quantities, but in lots of places).
- There are algorithms that require unsafe code to work efficiently, or to be practical (or both). For example, implementing a Linked List is quite a nightmare that to do it well you need unsafe. (See Learn Rust with Entirely Too Many Linked Lists)
- The point is that the unsafe code portions of a crate should be as small as possible and easy to prove correct. If it can be avoided, it should be avoided; unless there’s a strong reason to not to do so.
- Unsafe code blocks are not really unsafe. Most of the compiler guarantees still apply. It is close to regular C or C++ code in terms of safety, and most of us feel quite safe coding and running C++ programs.
Regarding on Actix and why it was a problem, first we need to understand that Actix is a web server, and it is intended to be exposed to the internet.
The HTTP protocol is really hard to implement right, completely, and error free. It’s not a simple protocol. An attacker could find a vulnerability leading to things that range from DoS to remote code execution.
In general we shouldn’t trust ANY web server. Anything that you put facing to the internet has to be proven to work properly. And here the issue is not about distrust on unsafe code (or C++ code), the issue is that a web server that is not widely used and scrutinized is potentially vulnerable to unknown attacks.
So for example, if you run NodeJS web servers, Python web servers, or anything similar, please consider removing them if they are reachable from the internet directly or indirectly (this is, proxying through Apache/Nginx/etc will still expose a handful of vulnerabilities). Instead, think about using another protocol to do this, like FastCGI, WSGI, or similar. Those protocols are simpler and harder to exploit vulnerabilities on them.
Actix in this case turns out that is so fast, that it even outperforms Nginx! So there’s no point on proxying through anything, you would lose so much performance in the way that it will make no sense. So Actix would be best as a web server directly exposed to the internet.
Also, Actix is new. There hasn’t been much time yet to carefully search for vulnerabilities. So we can expect that there might be something still hiding over there. It is still rapidly changing, so new bugs might appear at any point.
The problem with Actix was that the original author loved to use unsafe a lot. They quite enjoyed playing with Rust and unsafe. I am happy for them, but this is a recipe for disaster. Having more unsafe code than the bare minimum needed opens the door for unforeseen consequences.
The teams developing browsers like Firefox or Chromium are quite seasoned with C++ and they really know what they are doing, and they try to use all possible measures to reduce any memory related bugs, but even with that, it seems that 70% of the bugs of C++ applications are memory-related. (And Microsoft found this too)
I think this shows clearly why unsafe code should be minimized. But, does this mean that a Rust program with a tiny bit of unsafe code is less secure than a Python or NodeJS one? Nope.
Rust places a lot of restrictions on the code in such a way that the program is almost proven to be right, quite on the style of Haskell and other functional languages.
Having Actix fixed now, with unsafe code blocks reduced to the minimum, makes me more confident running it exposed to the internet than any Python/NodeJS server.
Rust has a lot of guarantees that just don’t exist in Python or Node. Also, the threading and async models impose proper restrictions to avoid programmers shooting themselves in the foot.
In case it wasn’t clear from the previous paragraphs, I wouldn’t put into such high standards to all parts required to do a web application. Still, unsafe needs to be minimized, but if doesn’t receive the user input, bugs will be harder to exploit.
Hope this explains my point of view on Actix and Unsafe. Also, I’m still learning Rust and this is just my humble opinion on the matter.
Thanks a lot to Tom MacWright who referenced to my article, it quite helps to see that my opinion is being read and taken into account.