In-Depth Security in Your Node.js Backend Applications

Mehmet Aziz Algüllü
Insider Engineering
6 min readJul 29, 2024

Hello! In this blog post, I will share in-depth information and tips on Node.js web application security from the perspective of a backend developer.

First, let’s make some inferences about which parts of a web backend application might cause security vulnerabilities:

It might originate from the application. For example:

  • There may be a lack of input validation and sanitization.
  • Dependencies and third-party libraries may contain vulnerabilities.
  • It may arise from improper user and session management.
  • It may result from not adding secure HTTP headers to HTTP responses.
  • Sensitive data may have been transmitted from the server to the client.

It might originate from the network. For example:

  • Lack of physical server security measures.
  • Not implementing rate limiting and absence of DDOS detection mechanisms.
  • Leaving unused ports exposed.

It might originate from data storage. For example:

  • Not encrypting sensitive data or using incorrect algorithms for encryption.
  • Defining incorrect access permissions.
  • Not backing up data or using incorrect methods for backups.
  • Lack of mechanisms necessary for data leakage and breach prevention.

If we assume that a backend developer is solely responsible for their application, what scenarios could we encounter and how can we produce solutions for these scenarios?

Input Validation ve Sanitization

Node.js forwards incoming requests to the web server directly to the application code without parsing. Therefore, we need to validate and sanitize the incoming content before processing it in the respective handler. If we fail to do so, the risks that may arise are:

  • SQL or NoSQL Injection: If user input is used directly in SQL or NoSQL queries without proper validation, it can lead to issues. Example:
  • “Cross-Site Scripting (XSS): Adding user input directly into HTML without proper validation can lead to issues. Example:
  • Command Injection & Remote Code Execution (RCE): Using user input directly in a server-side command without proper validation can lead to issues. Example:

How can we solve these issues? Utilizing packages like jsonschema for input validation and employing specific regex patterns to verify requested data.

jsonschema example

Authentication Management

Nearly every project we create requires a user account to assign roles to individuals using the system. Unless we take special care in designing our authentication and authorization mechanisms, malicious actors could gain unauthorized access to others’ accounts and perform actions within the project as if they were the account holders.

Risks and potential consequences of inadequate authentication management are:

  • A user being able to perform actions on behalf of another user: When designing endpoints where users can perform actions related to themselves, we need to add access_token validation. The access_token should be valid and should belong to the same person who initiated the request.
    Example: Let’s assume we have an endpoint named /send-money that transfers a specified amount based on senderId and receiverId data in the POST method body. If we do not validate the access_token in the request to this endpoint to ensure it is both valid and belongs to the person identified by receiverId, someone could transfer money on behalf of another person.
  • A user being able to obtain another user’s password by guessing: If user passwords are simple, one user could guess another user’s password and perform unauthorized actions. To prevent this, during the account creation stage, we can constrain users to choose passwords that are hard to guess and that can withstand various attacks such as dictionary attacks: passwords longer than a given number of characters, including a mix of special characters, numbers, uppercase, and lowercase letters, etc.
  • Absence of Multi-Factor Authentication (2FA): If a user’s password is compromised, someone else can access another person’s account. To prevent this, users can be authenticated into the system using a code from a device validated by an Authenticator application during each login. Additionally, limiting user session durations (for example, once per day) can significantly enhance security.

Dependencies and Third-Party Libraries

When creating a project, instead of coding each small piece from scratch, we can use many pre-coded and successful libraries, but these libraries must be reliable, regularly updated, and their bug fixes should not be delayed. Otherwise, they can introduce significant security risks.

Here are some examples:

  • In 2018, malicious code was discovered in a new version of the event-stream package. This code worked in conjunction with a dependency called flatmap-stream. Under specific conditions, the malicious code executed a piece of code that stole Bitcoin wallet information.
  • In 2019, a prototype pollution vulnerability was found in the lodash package. This vulnerability allowed attackers to modify the prototype of JavaScript objects, leading to unexpected behaviors.
  • In 2021, certain versions of the ua-parser-js package contained malicious code. This code attempted to install cryptocurrency mining software on the user’s computer. The malicious code was hidden within the package and designed to execute upon download.

Some methods we can generally apply:

  • Package Research: Research and ensure dependencies come from reliable sources before adding them. Check the maintenance status of popular packages on NPM.
  • Dependency Versioning: Pin dependency versions in your package.json file.
  • Security Scans in CI/CD Processes: Integrate security scanning tools like npm audit into CI/CD processes to automatically check for security issues when new dependencies are added to your codebase.
  • Static and Dynamic Analysis Tools: Use Static Application Security Testing (SAST) and Dynamic Application Security Testing (DAST) tools to detect security vulnerabilities in your codebase and running applications. Tools like Snyk and SonarQube can assist in this regard.
  • Minimal Dependencies: Minimize dependencies in projects to reduce the attack surface.

Secure HTTP Headers

We will use the HTTP response header structure to set metadata when our application returns a response. Some header parameters include custom data that we want to send from the application to the client, ensuring that the response reaches the user securely. In essence, certain specific header parameters are designed to address specific security vulnerabilities, and their use prevents weaknesses in those areas. Here are some examples:

  • XSS Protection (Cross-Site Scripting): Helmet enables browser XSS filters by adding the X-XSS-Protection header, providing protection against known XSS attacks.
  • Clickjacking Protection: By adding the X-Frame-Options header, it prevents the site from being embedded in an iframe by another site, thus protecting against clickjacking attacks.
  • MIME Type Sniffing Protection: Adding the X-Content-Type-Options header forces the browser to process files only with the defined MIME types, protecting against MIME type sniffing attacks.
  • Content Security Policy (CSP): By adding the CSP header, it ensures that resources (JavaScript, CSS, img, etc.) are loaded only from specified trusted sources, helping to prevent XSS and data injection attacks.
  • Privacy Protection: By adding the Referrer-Policy header, it controls referral information and enhances privacy.

As I mentioned above, there is a specialized library called Helmet used for adding secure header parameters. Helmet enables the addition of security parameters such as X-XSS-Protection and X-Frame-Options to HTTP headers, enhancing protection against attacks like XSS and clickjacking.

helmet example

In summary, making your application more secure may not be as difficult as you think. Acknowledging that your application may not always be used by good actors and considering that different scenarios, however unlikely, can occur, is actually the best security practice :)

See you in the next blog post!

--

--