Security analysts welcomed a recommendation from the US National Security Agency (NSA) last week for software developers to consider adopting languages such as C#, Go, Java, Ruby, Rust, and Swift to reduce memory-related vulnerabilities in code.
The NSA described these as “memory safe” languages that manage memory automatically as part of the computer language. They do not rely on the programmer to implement memory security and instead use a combination of compile time and run time checks to protect against memory errors, the NSA said.
The Case for Memory-Safe Languages
The NSA’s somewhat unusual advisory Nov. 10 pointed to widely used languages such as C and C++ as relying too heavily on programmers not to make memory-related mistakes, which it noted, continues to be the top cause for security vulnerabilities in software. Previous studies—one by Microsoft in 2019 and another from Google in 2020 related to its Chrome browser—for instance, both found 70% of vulnerabilities were memory safety issues, the NSA said.
“Commonly used languages, such as C and C++, provide a lot of freedom and flexibility in memory management while relying heavily on the programmer to perform the needed checks on memory references,” the NSA said. This often results in exploitable vulnerabilities tied to simple mistakes such as buffer overflow errors, memory allocation issues, and race conditions.
C#, Go, Java, Ruby, Rust, Swift, and other memory-safe languages do not completely eliminate the risk of these issues, the NSA said in its advisory. Most of them, for instance, include at least a few classes or functions that are non-memory safe and allow the programmer to perform a potentially unsafe memory management function. Memory-safe languages can sometimes also include libraries written in languages that contain potentially unsafe memory functions.
But even with these caveats, memory-safe languages can help reduce vulnerabilities in software resulting from poor and careless memory management, the NSA said.
Tim Mackey, principal security strategist at Synopsys Cybersecurity Research Center, welcomes the NSA’s recommendation. The use of memory-safe languages should, in fact, be the default for most applications, he says. “For practical purposes, relying on developers to focus on memory management issues instead of programming cool new features represents a tax on innovation,” he says. With memory-safe programming languages and associated frameworks, it is the authors of the language that ensure proper memory management and not the application developers, Mackey says.
Shift Can Be Challenging
Shifting a mature software development environment from one language to another can be hard, the NSA acknowledged. Programmers will need to learn the new language, and there are likely going to be newbie mistakes and efficiency hits during the process. The extent of memory security that is available can also vary significantly by language. Some might offer only minimal memory security, while others offer considerable protections around memory access, allocation and management.
In addition, organizations will need to consider how much of a tradeoff they are willing to make between security and performance. “Memory safety can be costly in performance and flexibility,” the NSA warned. “For languages with an extreme level of inherent protection, considerable work may be needed to simply get the program to compile due to the checks and protections.”
There are myriad variables in play when trying to port an application from one language to another, says Mike Parkin, senior technical engineer at Vulcan Cyber. “In a best-case scenario the shift is simple, and an organization can accomplish it relatively painlessly,” Parkin says. “In others, the application relies on features that are trivial in the original language but require extensive and expensive development to recreate in the new one.”
The use of memory-safe languages also doesn’t replace the need for proper software testing, Mackey cautions. Just because a programming language is memory safe doesn’t mean the language or applications developed on it are free from bugs.
Moving from one programming language to another is a risky proposition unless you have staff that already understands both the old language and the new one, Mackey says. “Such a migration is best done when the application is going through a major version update; otherwise there is the potential that inadvertent bugs are introduced as part of the migration effort,” he notes.
Mackey suggests that organizations consider using microservices when it comes to shifting languages. “With a microservices architecture, the application is decomposed into a set of services that are containerized,” Mackey says. “From the perspective of a programming language, there is nothing that inherently requires that each microservice be programmed in the same programming language as other services within the same application.”
Making the Move
“I think many organizations have already been switching away from C/C++ not only for the memory safety issue, but also for the overall ease of development and maintenance,” says Johannes Ullrich, dean of research at the SANS Technology Institute. “But there will still be legacy code bases that will have to maintained for many years to come.”
NSA’s advisory offered little insight into what might have prompted its recommendation at this juncture. But John Bambenek, principal threat hunter at Netenrich, advises that organizations not ignore it. “Memory vulnerabilities and attacks have been pervasive since the 1990s, so in general, this is good advice,” he says. “With that being said, as this is coming from the NSA, I believe this advice should take added urgency and is being driven by knowledge they have and we don’t.”