Methods such as these for C and C++ are interesting, and needed, but only solve a part of the problem.
As others have noted before, they do little good because they're opt-in. I think there's a bit of nuance to that which needs to be explored though, as I think it's less a problem that the extra checks are opt in, and more a problem of how we use and categorize libraries.
As long as we encourage dynamic and static library inclusion (and why wouldn't we, it's how we build upon the work of others), every language has a problem similar to how C and C++ are opt-in and you can't easily control the code you include or link. If you load openssl from Java or Rust or Go, you might have some benefit from a well defined API layer, but ultimately you are still beholden to the code openssl provides in their library.
Just as one of the real benefits of Rust or Java or Go is not necessarily that the code is completely safe, but that weird unsafe behavior usually requires special escape hatches which are easier to audit, what we need are ways to categorize the code we include, no matter the language it comes from, with appropriate labels that denote how strong the safeguard guarantees it was compiled with are and of which type, so we can make easier and better informed decisions on what to include and how to audit it easily when we do.
This applies to including something written in Rust as well. If someone is writing something in C++ and wants to include a library written in Rust, that it's written in Rust is only part of the picture. It's equally important to how often (as a total and as a percentage of code) the safety checks that language required (or that the developers opted into) where escaped in that library.
If the choice is a Rust library with 95% of the code in unsafe blocks or a C++ library that opted into multiple different safety checker systems and has almost no escapes from those requirements, Rust is not providing any real safety benefits in that situation, is it? What we need is better information exposed at a higher level to developers about what they're opting into when they use third party code, because we can all control what safety mechanisms we use ourselves, so that's mostly a solved problem.
Often missed here is that the Rust library author is strongly protected from faulty code written by Users. The C/C++ library author is not.
The most obvious examples of this are memory allocation. The C/C++ user claimed the buffer was large enough to contain the result. The Rust user received back an object that protected the memory and returned it at the right time.
But it could also be a file handle or mutex that used the Rust ownership patterns to protect the underlying data.
If I am using a library and the author can put in features that prevent misuse, I don't need to work so hard to use the library correctly. As soon as my safe code compiles I can be fairly sure with most rust libraries that I didn't break some unenforced rule.
That may be true but it doesn't help downstream users know what they're opting into. Knowing that a rust library can use no unsafe code is not the same as knowing that that library did use no unsafe code, in a similar way to knowing that a C library can be coded with the help of various tools to provide additional safery (in some cases beyond what rust provides natively) is not the same as knowing they did.
In other words, that something was written in a specific language is far too coarse and blunt an assessment to really know what you're getting into.
Rust libraries may be, in aggregate, far more likely to have additional safety than C libraries because of features rust provides that are generally used, but you can know nothing about the specific relative safety of a single rust library and C library without looking closer, at the code level. Having indicators of exactly that info surfaced in descriptions about libraries would be a major step forward IMO. I think it would also probably immediately benefit rust if it were to happen, as the info would cast many rust libraries in a beneficial light in comparison to others, but to me that's far less important than promoting better practices overall regardless of language by allowing users to better choose between them, regardless of language.
If the cybersecurity guidelines keep being improved upon, I expect security assements to be a requirement for 3rd party libraries, regardless of the language, just like we already have to do legal checks before being allowed to add them into the internal package server.
That’s a great point and I agree with it.
Just to play a bit of a “devil’s advocate”, GCd languages productivity boost comes from exactly this: both in Rust (where it is explicit) and in other low-level languages, low-level design decisions leak into public API interfaces. It’s great that it is explicit in Rust, but depending on what you work on it may be better to just have the runtime deal with it. (But clearly the C-FFI API surface is the worse of implicit requirements that may not be uphold at all)
I feel like a few languages are better than others in a related but not quite identical area:
Languages like Java and Go, while they CAN escape to native libraries, have cultures that tend to avoid that kind of thing. At least, in my projects, I have quite an easy time using zero native dependencies with those languages (except for the underlying kernel of course), and so I feel like there is a much lower chance of escape-hatch issues sneaking in.
They aren't built on a foundation of legacy C and C++ libraries - not even the crypto - and I find that to be an advantage.
This is at least partially because there is a performance overhead to calling out to C from Java or Go so eventually the optimal implementation of something will be in the language itself. Rust's zero-cost calls to/from C is a positive in that it gives you a large ecosystem of existing code to use but a negative in that people are more likely to just try to build "safe" wrappers around those instead of writing something safe in Rust. This is somewhat countered by the "rewrite it in Rust" folks but you still get more C wrappers than Java or Go.
This is a great point, and one that doesn't get enough attention. The article talks about using a static analysis tool, but usage of that tool is indeed opt-in, like you say.
I suspect a language could mitigate this with the ability to sandbox a library's code. That could be pretty slow though, but we could compile it to wasm and then use wasm2c to convert it back into native code. I wrote a bit about this idea in [0], but I'd love to see someone make this work for C++.
If you were starting a new project you could put lints in place to make these things enforced. But at some point you have all these lints and customizations in place, and you can't use old or 3rd party C++ code any more because of them, so you begin to ask, why not just use a new language where this stuff isn't pasted together with glue and bailing wire?
My point is really not about the code you write yourself, but the code you need to include in your project. Rare is the professional programmer that always gets to finish their project using only code they wrote themselves, and for many projects that's highly inadvisable (don't roll your own crypt unless you have a very good reason).
So, given that at times we will have to use external libraries, and given that even very safe languages often have escape hatches meaning you can't be sure the code of one language has more constraints than another, it would be great to have other indicators than the language it was written in that indicated what safety checks it uses.
If next year you're writing a new program in a language that hasn't even been invented as of now, and is viewed as safer than every language out today, what does that actually get you if one of your constraints is that you need to include and use openssl or one of a few forks for compatibility reasons? Wouldn't you rather be able to look at the available options and see that come opt into specific safety constraints, and have been good about not them circumventing them, and do so extremely easily? Network effects and existing known projects seem to have an inordinate amount of staying power, so we might as well deal with that as a fact.
The world is a messy place, but the more information we have the better our chances of making order out of it, even if temporarily.
People have this misconception that unsafe Rust is some other language. It's not. All it does is allow the use of raw pointers. So, all other Rust feature (ie type system) still work as they always did. So, you can really minimia the surface are of unsafe code. Not to mention seeing unsafe just means that something really low level is happening, and signals caution to the reader (or anyone editing the code), as opose to C++ where it's easy to forget you need to be alert, since you should be alert all the time really.
Exactly. Presumably there are some opt-in tools that are very strict about the inline assembly uses you have in C. I don't have any experience with them, but I'm sure they exist.
That's the whole point, it's less about the language, and more about the specifics of the code itself in a testable way. Saying something is written in C without accounting for a bunch of inline assembly is analogous to saying something is written in Rust and not accounting for a bunch of unsafe blocks. Not in that they are equivalently safe or unsafe, but that that high level assumptions because of the language fail because of the practices done within.
If I had to choose between two libraries written in C and one was pure C and one was 50% inlined assembly, and I viewed security and safety as more important for my use case, I know which one I would choose if that information was surfaced to me easily.
If you think I'm talking about rust vs C and not just using them as stand ins for any language pair, you're not understanding my point. Possibly because you're too focused on one language in particular, as I'm not focusing on any language in particular.
As others have noted before, they do little good because they're opt-in. I think there's a bit of nuance to that which needs to be explored though, as I think it's less a problem that the extra checks are opt in, and more a problem of how we use and categorize libraries.
As long as we encourage dynamic and static library inclusion (and why wouldn't we, it's how we build upon the work of others), every language has a problem similar to how C and C++ are opt-in and you can't easily control the code you include or link. If you load openssl from Java or Rust or Go, you might have some benefit from a well defined API layer, but ultimately you are still beholden to the code openssl provides in their library.
Just as one of the real benefits of Rust or Java or Go is not necessarily that the code is completely safe, but that weird unsafe behavior usually requires special escape hatches which are easier to audit, what we need are ways to categorize the code we include, no matter the language it comes from, with appropriate labels that denote how strong the safeguard guarantees it was compiled with are and of which type, so we can make easier and better informed decisions on what to include and how to audit it easily when we do.
This applies to including something written in Rust as well. If someone is writing something in C++ and wants to include a library written in Rust, that it's written in Rust is only part of the picture. It's equally important to how often (as a total and as a percentage of code) the safety checks that language required (or that the developers opted into) where escaped in that library.
If the choice is a Rust library with 95% of the code in unsafe blocks or a C++ library that opted into multiple different safety checker systems and has almost no escapes from those requirements, Rust is not providing any real safety benefits in that situation, is it? What we need is better information exposed at a higher level to developers about what they're opting into when they use third party code, because we can all control what safety mechanisms we use ourselves, so that's mostly a solved problem.