What makes a Language More Secure

Published: 26 Jul 2024

When it comes to the security of programming languages, the conversation often revolves around memory safety and typing. These features, while important, may not be as critical in the context of modern web applications, which typically already offer memory safety. Instead, for those conducting code reviews across multiple languages, a key component of secure applications is the quality and adoption of the standard library.

The Importance of Standard Libraries

As a code reviewer, you can usually tell the quality of a codebase based on how much it relies on the standard library. If developers are writing their own versions of things like uppercasing a string, extracting a filename from a path, or extracting an extension from a file—while those functionalities are already covered by the standard library—you know it is worth digging further. Either the developers don’t know the language well, or they like to reinvent the wheel. In both cases, this is a clear signal to keep reading, and bugs will rain. This is why a robust, well-documented, and well-adopted standard library can significantly enhance the security of your application. It reduces the need for developers to reinvent the wheel, minimizing the risk of introducing new vulnerabilities.

Frameworks and Documentation

Extending this principle to frameworks, the quality of documentation becomes paramount. Good documentation helps developers understand how to use libraries and frameworks securely. When the documentation is clear, comprehensive, and easy to follow, it guides developers toward best practices and helps them avoid common pitfalls. On the other hand, poor documentation can lead developers to write vulnerable code. One of my favorite examples of this can be found in the image below:

Bad Documentation Example

If you are familiar with regular expressions in Ruby, you know that this is a pretty bad idea...

Avoiding Surprises in Functions and Methods

Another critical aspect is having functions or methods that behave as expected. Surprising behavior can lead to security flaws. My favorite example of this is the Golang functions path.Clean and filepath.Clean used to "clean" a path. Canonicalization and sanitization can be confusing for developers. If you expect path.Clean and filepath.Clean to prevent directory traversal attacks, you are in for a surprise.

Some Things Should Come for Free

Security should be built-in, not bolted on. Password hashing is a perfect example. Developers should not have to implement their own password hashing algorithms or even install a library for this. The standard library or framework should provide robust, up-to-date password hashing out of the box, including support for algorithm rotation to keep up with evolving security standards.

The Quality of Search Results

The quality of the first results on Google for a language is also key. A lot of results for key functions get poisoned by SEO-seeking websites and provide incomplete, incorrect, or completely insecure snippets of code. The ranking of standard library documentation in search engines when developers look for solutions to their problems ("Encrypting Passwords in PHP," "Hashing Passwords in C#," "Avoiding XSS in Python") can make the difference between introducing and not introducing vulnerable code in a codebase.

Conclusion

In summary, while memory safety and typing are important, the real strength of a secure programming language lies in the quality of its standard library, the clarity of its documentation, and the predictability of its functions. By focusing on these areas, developers can build more secure web applications and avoid common security pitfalls. Remember, don’t reinvent the wheel when it comes to security—use the tools and resources provided by the language and framework to your advantage.

Photo of Louis Nyffenegger
Written by Louis Nyffenegger
Founder and CEO @PentesterLab