https://timmmm.github.io/curl-vulnerabilities-rust/ Would Rust secure cURL? Rewriting programs in Rust has become a bit of a meme and one program that has been discussed a lot is cURL. The first time people suggested rewriting cURL in Rust, the main author Daniel Stenberg wrote an article about why cURL is written in C and wouldn't be rewriten in Rust. It includes this section: C is not the primary reason for our past vulnerabilities There. The simple fact is that most of our past vulnerabilities happened because of logical mistakes in the code. Logical mistakes that aren't really language bound and they would not be fixed simply by changing language. Of course that leaves a share of problems that could've been avoided if we used another language. Buffer overflows, double frees and out of boundary reads etc, but the bulk of our security problems has not happened due to curl being written in C. Three years later news arrived that some Rust code would be used in cURL, though only as an optional HTTP backend - it isn't a full rewrite. This news reignited the discussion (Reddit, Hacker News). It seems that some people are still under the impression that it is possible to write memory-safe C, and based on the above quote that cURL is memory safe C! Is this true? Are the majority of cURL's security vulnerabilities logic mistakes? It's easy to find out. The cURL authors have a great list of (known) cURL security vulnerabilities. If you skim it it becomes immediately obvious that no, cURL has plenty of memory safety bugs. Since there's a nice list with great descriptions of each bug it seems like a nice opportunity to measure how many bugs Rust would have prevented. I think "how many historical bugs would this have prevented" is a really good way of judging a programming language or feature. For example this great study shows that using Typescript would have prevented approximately 15% of all bugs that you find in typical Javascript code. It's hard to argue against static types with evidence like that. I went through the entire list of cURL security issues, and categorised all of the bugs, together with whether or not I think Rust would have prevented them. I did not look at the code for all of them (e.g. if it says "buffer overflow" then it's pretty clear Rust would prevent it), so take these results with a small pinch of salt. Corrections welcome! Results There are 95 bugs. By my count Rust would have prevented 53 of these. 1. 47 are standard memory errors (overflows, use-after free, etc.). Rust would definitely prevent these. For comparison, Google found that 70% of Chrome bugs are memory errors. 2. 5 are integer overflows, which Rust does not prevent by default in release mode (though it can via an optional flag), but they lead to memory errors which it does prevent. 3. 1 was through misuse of fgets(). Rust does not stop you making difficult to use APIs, but it definitely reduces the chance, e.g. by warning you if you don't use a Result. It's hard to imagine this bug happening with Rust. image/svg+xml No Unlikely Possibly Likely Yes 0 25 50 75 100 Bug count Would Rust have prevented the bug? The remaining bugs are logic errors of some kind or another. There are definitely several of the sort "we should have checked thing, but didn't" that Rust couldn't help with. But there are also a decent number of other bugs that come from cURL doing ad-hoc inline character-by-character parsing of just about everything, whereas in Rust you would probably use a library to fully parse things. I've generously counted these as No in my tally but I suspect they would be less likely with Rust. Conclusion It is safe to say that nobody can write memory-safe C, not even famous programmers that use all the tools. Here's Daniel in 2017: We keep scanning the curl code regularly with static code analyzers (we maintain a zero Coverity problems policy) and we run the test suite with valgrind and address sanitizers. 12 out of 15 of cURL's security issues since that statement have been memory errors (or integer overflows leading to memory errors). Rust proponents may seem overly zealous and I think this has led to a minor backlash of people thinking "Rust can't be that great surely; these people must be confused zealots, like Trump supporters or Christians". But it's difficult to argue with numbers like these. --------------------------------------------------------------------- Some other observations Some random things I noticed when reading the list. * Some of these bugs are really complicated. It is not surprising at all that humans missed them. Only automated tools could detect or prevent these. * A significant number of bugs (about 9) come from cURL trying to reuse connections and state that it shouldn't. * The cURL descriptions of their security bugs are great. The list These are how I classified the bugs. If I've got something drastically wrong let me know. Rust # Vulnerability Classification prevention (0=no, 4= yes) 95 wrong connect-only Logic, pointers 2 connection 94 curl overwrite local Logic 1 file with -J Partial password leak 93 over DNS on HTTP Logic, quoting 1 redirect 92 FTP-KRB double-free Memory 4 91 TFTP small blocksize Memory 4 heap buffer overflow 90 Windows OpenSSL Logic 0 engine code injection 89 TFTP receive buffer Memory 4 overflow 88 Integer overflows in Integer overflow leading to 3 curl_url_set memory NTLM type-2 87 out-of-bounds buffer Memory 4 read 86 NTLMv2 type-3 header Memory 4 stack buffer overflow 85 SMTP end-of-response Memory 4 out-of-bounds read 84 warning message Memory 4 out-of-buffer read 83 use-after-free in Memory 4 handle close SASL password Integer overflow leading to 82 overflow via integer memory 3 overflow NTLM password Integer overflow leading to 81 overflow via integer memory 3 overflow 80 SMTP send heap buffer Memory 4 overflow 79 FTP shutdown response Memory 4 buffer overflow 78 RTSP bad headers Memory 4 buffer over-read 77 RTSP RTP buffer Memory 4 over-read 76 LDAP NULL pointer Memory 4 dereference FTP path trickery 75 leads to NIL byte out Memory 4 of bounds write 74 HTTP authentication Logic 0 leak in redirects 73 HTTP/2 trailer Memory 4 out-of-bounds read 72 SSL out of buffer Memory 4 access 71 FTP wildcard out of Memory 4 bounds read 70 NTLM buffer overflow Integer overflow leading to 3 via integer overflow memory 69 IMAP FETCH response Memory 4 out of bounds read FTP PWD response 68 parser out of bounds Memory 4 read 67 URL globbing out of Memory 4 bounds read 66 TFTP sends more than Memory 4 buffer size 65 FILE buffer read out Memory 4 of bounds URL file scheme drive 64 letter buffer Memory 4 overflow TLS session 63 resumption client Logic, reuse 0 cert bypass (again) 62 --write-out out of Memory 4 buffer read 61 SSL_VERIFYSTATUS Logic 0 ignored 60 uninitialized random Type error 4 59 printf floating point Memory 4 buffer overflow Win CE schannel cert 58 wildcard matches too Logic 0 much Win CE schannel cert 57 name out of buffer Memory 4 read 56 cookie injection for Logic, difficult to use API 3 other servers 55 case insensitive Logic, terrible function name 0 password comparison OOB write via 54 unchecked Memory 4 multiplication 53 double-free in Memory 4 curl_maprintf 52 double-free in krb5 Memory 4 code 51 glob parser write/ Memory 4 read out of bounds 50 curl_getdate read out Memory 4 of bounds URL unescape heap 49 overflow via integer Memory 4 truncation 48 Use-after-free via Memory 4 shared cookies 47 invalid URL parsing Logic, used regex, now 2 0 with '#' problems 46 IDNA 2003 makes curl Logic, unicode insanity 1 use wrong host curl escape and Integer overflow leading to 45 unescape integer memory 3 overflows 44 Incorrect reuse of Logic, reuse 0 client certificates TLS session 43 resumption client Logic, reuse 0 cert bypass Re-using connections 42 with wrong client Logic, reuse 0 cert 41 use of connection Memory 4 struct after free 40 Windows DLL hijacking Windows API nonsense 0 TLS certificate check 39 bypass with mbedTLS/ Logic 0 PolarSSL remote file name path 38 traversal in curl Logic, quoting 0 tool for Windows NTLM credentials 37 not-checked for proxy Logic, reuse 0 connection re-use SMB send off Memory, but I think this is 36 unrelated memory still reading from valid 0 contents allocated memory, heartbleed style lingering HTTP 35 credentials in Logic, reuse 0 connection re-use sensitive HTTP server 34 headers also sent to Logic 0 proxies host name out of 33 boundary memory Memory 4 access cookie parser out of 32 boundary memory Memory 4 access Negotiate not treated 31 as Logic 0 connection-oriented Re-using 30 authenticated Logic, reuse 0 connection when unauthenticated 29 darwinssl certificate Logic, reuse 0 check bypass 28 URL request injection Logic 0 27 duphandle read out of Memory 4 bounds 26 cookie leak for TLDs Logic, parsing 0 25 cookie leak with IP Logic 0 address as domain not verifying certs 24 for TLS to IP address Logic 0 / Winssl not verifying certs 23 for TLS to IP address Logic 0 / Darwinssl IP address wildcard 22 certificate Logic 0 validation 21 wrong re-use of Logic 0 connections 20 re-use of wrong HTTP Logic, reuse 2 NTLM connection 19 cert name check Logic 0 ignore GnuTLS 18 cert name check Logic 0 ignore OpenSSL 17 URL decode buffer Memory 4 boundary flaw 16 cookie domain Logic 0 tailmatch 15 SASL buffer overflow Memory 4 14 SSL CBC IV Logic 0 vulnerability 13 URL sanitization Logic, parsing 0 vulnerability 12 inappropriate GSSAPI Logic 0 delegation 11 local file overwrite Logic, parsing 0 10 data callback Memory 4 excessive length 9 embedded zero in cert Logic, null-terminated strings 4 name 8 Arbitrary File Access Logic 0 7 GnuTLS insufficient Logic 0 cert verification 6 TFTP Packet Buffer Memory 4 Overflow 5 URL Buffer Overflow Memory 4 4 NTLM Buffer Overflow Memory 4 3 Authentication Buffer Memory 4 Overflows Proxy Authentication 2 Header Information Logic 0 Leakage 1 FTP Server Response Memory 4 Buffer Overflow