Secure coding is the practice of developing computer software in a way that guards against the accidental introduction of security vulnerabilities. Defects, bugs and logic flaws are consistently the primary cause of commonly exploited software vulnerabilities.
Secure code guidelines
Secure code guidelines are best practices which are set by organization, individuals, or anyone else to provide a set of standards or rules to follow that enable a person to write secure code. They are different for every programming language, and different guidelines may be set for the same language or platform by different organizations. Adopting a secure code guideline which is in-par with your requirements and company culture ensures quality software, and enhances awareness for security in the team.
T> ## Enforcing Secure Code Guidelines T> To further strengthen the adoption in your team it is possible to create linting rules and git hooks that ensures source code that is being added to the source code repository is actually following the standards set for a secure code guideline. T> OWASP maintains a secure code guideline document as a reference.
The following sub-sections provide a collection of topics that may be employed to adhere to secure code guidelines: Node.js versioning, user input, and common programmer pitfall around Node.js event loop and encryption.
As software evolves, APIs are doomed to be modified as they receive updates or get completely replaced with a newer set of APIs. This is true for Node.js and has happened in prior releases as well.
Aside of the Node.js documentation website, several ways of tracking breaking, or major API changes include:
- The official Node.js Changelog
- The Node.js community employs a methodology of soft-deprecation for APIs by logging out messages of deprecation warnings. Developers, whom are often sensitive to their application debug or console output can easily catch these notifications and take them into account. Node.js pending deprecation CLI option node –pending-deprecation (or set the NODE_PENDING_DEPRECATION=1 environment variable) will emit deprecation warnings from the node process.
These days attackers aim at application layers as they attempt to exploit vulnerable application code which isn’t handling input correctly. Un-trusted user input is the first line of defense for an application program code, and mitigating it early in the software development life-cycle is crucial in setting the security boundaries correctly and the foundations for a secure application design.
Failure of securely handling un-trusted user input may result in:
- Injection attacks
- Information Disclosure
- Buffer Overflows leading to system compromise or memory leaks
A program performs input validation to ensure that the received data structure is valid, and as-expected for further handling and manipulation. Un-trusted data, such as that which is originating from user input, may contain malicious or invalid data which can lead the program to perform unwanted tasks or cause side-effects.
- Existence – Whether the input data exists.
- Length – When length matters, check that input data is constraint to a specific length or expected size.
- Type – Confirming that a received user data matches an expected type. Ideally, where strict type checking is possible, such as with TypeScript, this is the preferred method. Otherwise, either basic language types or when expecting all numerics, or all characters, it is best to at least match the expected data.
- Range – Where the range of values is constraint by your application logic, it is best to confirm that received data indeed matches the range.
- Blacklisting and Whitelisting – Blacklisting is often less advised due to the fact that it is based on a perceived knowledge of vulnerabilities that the user expects, yet often times it is circumvented using new attacks. Whitelisting is advised as it matches only an expected user input.
Node.js regular expressions are a big no-no due to the horrible ReDoS attacks that can bring down a server. With Node.js being single threaded in nature this becomes super critical and must be carefully observed.
Often, programmers tend to write their own Regular Expressions to validate input, for example, testing whether a received data input matches an e-mail address, a URL address and so on. While regex seem like an easy and natural solution for validating input, if not done correctly, they can be abused using attack vectors like ReDoS.
The ideal solution for validating user input is to use one of the following libraries which are constantly tested for security:
- npm’s Validator package – provides validation and sanitization capabilities
- OWASP’s EASPIJS – OWASP’s own implementation of that provides both input validation as well as output encoding capabilities.
Output Encoding is a mechanism that is used at the presentation layer, where data that is passed from the server-side to a view, such as a web browser, which should be encoded or sanitized from malicious payloads which seek to exploit vulnerabilities in the presentation layer engine.
Implementing output encoding mitigates attacks such as Cross Site Scripting (XSS) because such malicious data is being encoded when it is output by the application to the presentation layer, hence circumventing any attempt to trick, or trigger an incorrect execution that is not a simple string representation of the data.
Output Encoding is often referred to as Output Escaping, Output Handling. T> Often times another term is associated with output encoding – Canonicalization, which means to convert the untrusted data input into an expected representation in the correct context. For example, a given user input of <script>alert()</script> will be canonicalized to <script>alert();</script>
Safe Regular Expressions
There is no magic to apply on regular expressions to make them safe, but rather the secret lies in crafting a correct, performant and safe regular expression pattern. Software engineers should pay attention for increased security implications when creating regular expressions.
Taking the above example of /^((abc)*)+$/ is simply a human error in writing a pattern, even though it works it’s not safe to use. The same regular expression match would also work if the following pattern was used /^(abc)*$/, which is safe as it is not repeating a more complex sub-expression.
OWASP’s website provides a short list of common validated regular expressions which are safe to use as well as links to other useful RegEx resources.