Top 10 Best Practices To Secure Node.js Apps in Production

Learn how to safeguard your Node.js applications against malicious users and ensure the uninterrupted, seamless operation of your app.

In today’s interconnected digital landscape, ensuring the security of web applications is of utmost importance. Node.js, with its efficient and scalable runtime environment, has become a popular choice for building server-side applications. However, as Node.js applications are deployed into production environments, they become potential targets for cyber threats and attacks. Therefore, it is vital to implement robust security measures to protect these applications and the sensitive data they handle.

This article explores the top 10 best practices to secure Node.js apps in production. By following these practices, developers, and system administrators can fortify their Node.js applications against common vulnerabilities and safeguard them from potential exploits. From keeping the runtime environment up-to-date to implementing secure authentication and encryption, these best practices cover a wide range of security considerations.

By adhering to these recommendations, developers can ensure that their Node.js applications are resilient and protected, providing users with a secure and reliable experience. Whether you are building a small-scale web application or a large enterprise-level system, incorporating these security practices into your development process will significantly enhance the security posture of your Node.js apps.

In the following sections, we will delve into each best practice in detail, exploring the rationale behind it and providing practical guidance on its implementation. By the end of this article, you will have a comprehensive understanding of the essential security measures to apply when deploying Node.js applications in production environments.

Let’s dive into the top 10 best practices to secure your Node.js apps and fortify them against potential threats, ensuring the integrity, confidentiality, and availability of your valuable data.

Top 10 Essential Measures for Ensuring Security in Node.js Applications

  1. Restrict SQL Injection Attacks
  2. Restrict XSS (Cross-Site Scripting) Attacks
  3. Restrict DOS (Denial-of-Service) Attacks
  4. Restrict CSRF (Cross-Site Request Forgery) Attacks
  5. Enable HTTP Security Headers
  6. Implement Robust Authentication
  7. Scan For Vulnerable Dependencies
  8. Limit Request Payload Size
  9. Use Security Linters
  10. Setup Logging and Monitoring

1. Restrict SQL Injection Attacks

SQL injection attacks are a common and critical vulnerability that can be exploited to gain unauthorized access to a database or manipulate its contents. Fortunately, there are several effective measures you can take to restrict SQL injection attacks in your Node.js application. Let’s explore some best practices:

1.1 — Parameterized Queries

Utilize parameterized queries or prepared statements when interacting with the database. Parameterized queries separate SQL logic from user-supplied data, preventing malicious input from altering the structure of the SQL query. This technique ensures that user inputs are treated as data values rather than executable code.

Example using the mysql module:

const mysql = require('mysql');
const connection = mysql.createConnection({ /* connection details */ });

const query = 'SELECT * FROM users WHERE username = ? AND password = ?';
const values = ['admin', 'password123'];

connection.query(query, values, (error, results) => {
// Handle query results
});

1.2 — Input Validation and Sanitization

Implement input validation and sanitization techniques to ensure that user-supplied data meets the expected criteria. Use libraries like validator.js or Joi to validate input against specific data types, formats, or constraints. Additionally, sanitize user inputs to remove or escape any potentially harmful characters.

Example using the validator.js library:

const validator = require('validator');

const userInput = req.body.username;

if (validator.isAlphanumeric(userInput)) {
// Proceed with the query
} else {
// Reject the input or show an error message
}

1.3 — Object-Relational Mapping (ORM) Libraries

Consider using ORM libraries, such as Sequelize or Knex.js, which provide an abstraction layer for database operations. ORM libraries automatically handle parameterized queries and sanitize user inputs, reducing the risk of SQL injection vulnerabilities.

Example using Sequelize:

const Sequelize = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', { /* connection details */ });

const User = sequelize.define('user', {
username: Sequelize.STRING,
password: Sequelize.STRING
});

User.findOne({ where: { username: userInput } })
.then(user => {
// Handle the query result
})
.catch(error => {
// Handle errors
});

1.4 — Stored Procedures

Consider using stored procedures provided by your database management system. Stored procedures encapsulate SQL logic within the database itself, reducing the risk of SQL injection attacks. By calling stored procedures with sanitized parameters, you can mitigate SQL injection vulnerabilities.

1.5 — The Least Privilege Principle

Follow the principle of least privilege when configuring database access for your Node.js application. Create a separate database user with the minimum required privileges necessary for the application to operate successfully. Restrict the user’s permissions to only execute the required queries and prevent direct access to sensitive database operations.

1.6 — Regular Updates and Security Audits

Stay up-to-date with the latest security patches and updates for your database management system. Regularly review the security configuration and conduct security audits to identify any potential vulnerabilities. Stay informed about common SQL injection techniques and new attack vectors to proactively protect your application.

2. Restrict XSS (Cross-Site Scripting) Attacks

XSS (Cross-Site Scripting) attacks pose a significant security risk to web applications, including those built with Node.js. These attacks involve injecting malicious scripts into web pages, which can lead to unauthorized data access, session hijacking, or other malicious activities. To restrict XSS attacks in your Node.js application, consider implementing the following best practices:

2.1 — Input Validation and Sanitization

Implement strict input validation and sanitization to prevent untrusted data from being rendered as active content in the browser. Use libraries like validator.js or DOMPurify to sanitize user inputs, removing or escaping any potentially malicious code or characters.

Example using DOMPurify:

const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');

const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);

const userInput = req.body.comment;

const sanitizedInput = DOMPurify.sanitize(userInput);

2.2 — Content Security Policy (CSP)

Implement a Content Security Policy (CSP) to restrict the execution of untrusted scripts in the browser. CSP defines a set of rules that specify which types of content can be loaded and executed on a web page. By whitelisting trusted sources for scripts, stylesheets, and other resources, you can effectively mitigate XSS attacks.

Example of setting CSP headers in Express.js:

const express = require('express');
const app = express();

app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self' example.com");
next();
});

2.3 — Templating Engines

If you are using a templating engine, ensure that it automatically escapes user-generated content by default. Popular templating engines like Handlebars and EJS have built-in mechanisms to prevent XSS attacks by escaping dynamic content. Make sure to enable auto-escaping and review your templates to ensure all user inputs are properly escaped.

Example using EJS:

const ejs = require('ejs');
const template = `<h1><%= user.name %></h1>`;

const data = {
name: `<script>alert('XSS Attack');</script>`
};

const rendered = ejs.render(template, { user: data }, { escape: true });

2.4 — HTTP-only Cookies

Utilize HTTP-only cookies to mitigate the risk of XSS attacks targeting session data. By setting the httpOnly flag when creating cookies, you ensure that they can only be accessed by the server and are not accessible to client-side scripts. This prevents attackers from stealing or manipulating sensitive session information.

Example using the cookie library:

const cookie = require('cookie');
const express = require('express');
const app = express();

app.get('/', (req, res) => {
const sessionData = {
user_id: 123,
username: 'john'
};

const sessionCookie = cookie.serialize('session', JSON.stringify(sessionData), {
httpOnly: true,
secure: true, // Enable this if using HTTPS
sameSite: 'strict'
});

res.setHeader('Set-Cookie', sessionCookie);
res.send('Hello World');
});

2.5 — Regular Updates and Security Audits

Stay up-to-date with security patches for the libraries and frameworks you use in your Node.js application. Keep an eye on security advisories and updates from the Node.js community. Regularly review and audit your codebase to identify and fix any potential XSS vulnerabilities.

3. Restrict DOS (Denial-of-Service) Attacks

Restricting Denial-of-Service (DoS) attacks in Node.js requires implementing measures to mitigate excessive resource consumption and ensure the availability of your application even under attack. While it may not be possible to eliminate the risk of DoS attacks, you can take several steps to minimize their impact. Here are some best practices to help you restrict DoS attacks in your Node.js application:

3.1 — Implement Rate Limiting

Enforce rate limiting to restrict the number of requests a client can make within a specific time frame. This prevents an individual client from overwhelming your application with a flood of requests. Consider using libraries like express-rate-limit or limiter to implement rate limiting based on IP addresses, request headers, or other criteria.

Example using express-rate-limit middleware:

const express = require('express');
const rateLimit = require('express-rate-limit');
const app = express();

const limiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100 // Limit each IP to 100 requests per minute
});

app.use(limiter);

3.2 — Use Caching

Leverage caching mechanisms to reduce the load on your application and improve its resilience against DoS attacks. Implement caching at different layers, such as in-memory caches like Redis, or external caching services like Memcached or CDN (Content Delivery Network) solutions. Caching can help serve static or frequently accessed data without invoking resource-intensive operations.

3.3 — Implement Request Validation and Filtering

Validate and filter incoming requests to discard malicious or malformed requests before they reach resource-intensive parts of your application. Utilize validation libraries like Joi, or custom request validation middleware to ensure that requests meet the required criteria. Reject or ignore requests that do not adhere to expected patterns, reducing the processing overhead.

3.4 — Enable Keep-Alive Connections

Configure your Node.js server to enable Keep-Alive connections. Keep-Alive allows multiple requests to be served over a single TCP connection, reducing the overhead of establishing new connections for each request. This helps conserve server resources and mitigate the impact of connection-based DoS attacks.

Example using the http module:

const http = require('http');

const server = http.createServer((req, res) => {
// Request handling logic
});

server.keepAliveTimeout = 60000; // Set the keep-alive timeout to 60 seconds

3.5 — Implement Timeouts

Set appropriate timeouts for request and response handling to limit the impact of slow or stalled requests. Use the timeout option available in libraries like Express.js or directly set timeout values for specific operations. By terminating long-running requests, you can free up resources and ensure that your application remains responsive.

Example using Express.js:

const express = require('express');
const app = express();

app.use((req, res, next) => {
req.setTimeout(5000); // Set request timeout to 5 seconds
res.setTimeout(5000); // Set response timeout to 5 seconds
next();
});

// Rest of your application code

3.6 — Distributed Denial-of-Service (DDoS) Mitigation

Consider using DDoS mitigation services (like Cloudflare) to protect your application from large-scale DDoS attacks. These services employ various techniques such as traffic analysis, rate limiting, and IP filtering to identify and mitigate DDoS attack traffic before it reaches your application.

3.7 — Network and Infrastructure Hardening

Implement network and infrastructure-level measures to protect your Node.js application from DoS attacks. This includes setting up firewalls, intrusion detection and prevention systems (IDPS), load balancers, and proper network segmentation. Regularly monitor network traffic and implement anomaly detection mechanisms to identify and respond to potential attacks.

4. Restrict CSRF (Cross-Site Request Forgery) Attacks

Restricting Cross-Site Request Forgery (CSRF) attacks in Node.js involves implementing countermeasures that prevent malicious actors from exploiting the trust between a user and a website to perform unauthorized actions on behalf of the user. Here are some best practices to help you restrict CSRF attacks in your Node.js application:

4.1 — Implement CSRF Tokens

Utilize CSRF tokens to validate the authenticity of requests. Generate a unique CSRF token for each user session and include it in forms or as a custom header in AJAX requests. On the server side, validate the received token with the one stored in the user’s session to ensure it matches.

Example using the csurf middleware:

const express = require('express');
const csrf = require('csurf');
const app = express();

// Enable CSRF protection for all routes
app.use(csrf({ cookie: true }));

// Include the CSRF token in the response locals
app.use((req, res, next) => {
res.locals.csrfToken = req.csrfToken();
next();
});

// Rest of your application code

4.2 — Set the “SameSite” Attribute

Set the “SameSite” attribute for cookies to control when they are sent with cross-site requests. By setting it to “Strict” or “Lax,” you can restrict the transmission of cookies to only same-site requests, mitigating the risk of CSRF attacks.

Example using the cookie library in Express.js:

const cookie = require('cookie');
const express = require('express');
const app = express();

app.use((req, res, next) => {
const csrfToken = req.csrfToken();

// Set the CSRF token as a cookie with the SameSite attribute
res.setHeader('Set-Cookie', cookie.serialize('csrfToken', csrfToken, {
sameSite: 'Strict',
secure: true, // Enable this if using HTTPS
httpOnly: true
}));

next();
});

// Rest of your application code

4.3 — Verify Origin and Referrer Headers

Check the Origin and Referer headers of incoming requests to ensure they match the expected values. Validate that the request originates from an authorized domain and is not a cross-origin request. However, note that the Referer header can be spoofed, so relying solely on it is not sufficient.

4.4 — Use Anti-CSRF Libraries

Consider using anti-CSRF libraries like csurf, helmet, or csurf-elixir to simplify the implementation of CSRF protection. These libraries handle token generation, validation, and integration with popular frameworks, making it easier to secure your Node.js application against CSRF attacks.

4.5 — Apply Strict CORS Policies

Implement strict Cross-Origin Resource Sharing (CORS) policies to control which origins are allowed to make cross-origin requests to your application. Use the cors middleware or set appropriate headers to specify the allowed origins, methods, and headers. This helps prevent unauthorized cross-origin requests that could lead to CSRF attacks.

Example using the cors middleware:

const express = require('express');
const cors = require('cors');
const app = express();

// Enable CORS with specific options
app.use(cors({
origin: 'https://www.example.com',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization']
}));

// Rest of your application code

5. Enable HTTP Security Headers

To enable HTTP security headers in a Node.js application, you can use the helmet package. Helmet is a middleware that helps secure your application by setting various HTTP headers. Here’s how you can enable HTTP security headers using Helmet in Node.js:

Install the helmet package by running the following command in your Node.js project directory:

npm install helmet

Require the helmet package at the top of your Node.js file:

const helmet = require('helmet');

Use the helmet middleware in your Express.js application:

const express = require('express');
const app = express();

// Use helmet middleware
app.use(helmet());

By default, Helmet sets several security headers. However, you can customize the headers according to your requirements. For example, to enable the Content-Security-Policy header, you can use the helmet.contentSecurityPolicy() middleware:

app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'"],
},
})
);

In the above example, we set the defaultSrc to allow resources from the same origin (‘self’), and we allow ‘unsafe-inline’ and ‘unsafe-eval’ for JavaScript (scriptSrc) and inline styles (styleSrc). You can adjust these directives according to your application’s needs.

6. Implement Robust Authentication

Implementing robust authentication in a Node.js application involves several steps. Here’s a high-level overview of the process:

6.1 — Choose an Authentication Strategy

There are various authentication strategies you can choose from, such as session-based authentication, token-based authentication (e.g., JWT), or OAuth. Consider the requirements of your application and choose the strategy that best fits your needs.

6.2 — Securely Store User Credentials

When users register, securely store their credentials in a database. Hash passwords using a strong hashing algorithm, such as bcrypt or Argon2, to protect against data breaches.

6.3 — Create User Registration and Login Routes

Set up routes for user registration and login. Validate user input and authenticate users using the chosen authentication strategy. Generate and issue authentication tokens or session cookies as needed.

6.4 — Implement Password Reset and Change Password Functionality

Allow users to reset their passwords if they forget them or change their passwords if needed. This typically involves sending password reset emails with a secure token and providing routes to handle the password reset process.

6.5 — Implement Middleware for Authentication

Create middleware that checks the authentication status of incoming requests. This middleware should validate the authentication token or session and grant access to protected routes only to authenticated users.

6.6 — Implement Authorization

Define user roles and permissions to control access to different parts of your application. Implement authorization middleware that checks if a user has the necessary permissions to access a specific resource or perform an action.

6.7 — Secure Sensitive Data

If your application handles sensitive data, ensure it’s protected. Use encryption, such as HTTPS/TLS, to secure data in transit. Encrypt sensitive data at rest, for example, by using a secure database or encrypting specific fields.

7. Scan For Vulnerable Dependencies

To scan for vulnerable dependencies in a Node.js application, you can use a package vulnerability scanner. One popular tool for this purpose is the npm audit command, which is built into the npm package manager. Here’s how you can use npm audit to scan for vulnerable dependencies:

Open your terminal or command prompt and navigate to your Node.js project directory. Run the following command to perform a vulnerability scan:

npm audit

The npm audit command will analyze your project’s dependencies and provide a report on any known vulnerabilities. It will categorize the vulnerabilities as “high,” “moderate,” or “low” severity based on their impact. It will also suggest actions to fix the vulnerabilities.

Review the output of the npm audit command. It will list the vulnerable packages, their versions, and a description of the vulnerability. It will also suggest an update or provide instructions on how to fix the vulnerability.

To automatically fix the vulnerabilities that have known updates, you can run the following command:

npm audit fix

This command will attempt to update vulnerable packages to their latest versions, applying fixes where available. However, please note that this command may not be able to fix all vulnerabilities, particularly if there are breaking changes or if the maintainers of the packages have not released patches.

After running npm audit fix, review the changes made to your project’s dependencies. Verify that the fixes did not introduce any compatibility issues or break your application’s functionality. If you encounter issues, you may need to manually update or replace certain packages to resolve the vulnerabilities.

It’s important to regularly perform vulnerability scans on your dependencies and keep them up to date to minimize the risk of potential security breaches. Additionally, consider using automated vulnerability scanning tools, such as Snyk, npm audit-ci, or retire.js, for more comprehensive and continuous monitoring of your project’s dependencies. These tools can provide detailed reports and notifications about vulnerabilities and suggest remediation steps.

8. Limit Request Payload Size

To limit the request payload size in a Node.js application, you can use middleware to intercept incoming requests and enforce a size limit. Here’s an example using the express framework:

Install the express package if you haven’t already:

npm install express

Require the necessary modules and create an instance of the express application:

const express = require('express');
const app = express();

Use the express.json() middleware to parse incoming JSON payloads:

app.use(express.json());

Define a custom middleware function to limit the request payload size. This middleware will check the Content-Length header of the request and reject the request if it exceeds the specified size limit:

const limitPayloadSize = (req, res, next) => {
const MAX_PAYLOAD_SIZE = 1024 * 1024; // 1MB

if (req.headers['content-length'] && parseInt(req.headers['content-length']) > MAX_PAYLOAD_SIZE) {
return res.status(413).json({ error: 'Payload size exceeds the limit' });
}

next();
}

In this example, the maximum payload size is set to 1MB (1024 * 1024 bytes), but you can adjust it to your desired size. Use the limitPayloadSize middleware in your application to limit the request payload size:

app.use(limitPayloadSize);

With this implementation, any incoming requests with a payload size exceeding the defined limit will receive a 413 Payload Too Large response.

Keep in mind that this approach only limits the size of JSON payloads. If you’re handling other types of payloads, such as file uploads, you may need to employ additional middleware or techniques specific to those scenarios.

9. Use Security Linters

Using security linters in Node.js is an effective way to identify and prevent common security vulnerabilities in your codebase. Here’s how you can incorporate security linters into your Node.js development workflow:

There are several security linters available for Node.js projects. One popular option is eslint-plugin-security, which is an ESLint plugin specifically designed to detect security issues. Install it by running the following command:

npm install eslint eslint-plugin-security --save-dev

If you haven’t already set up ESLint for your Node.js project, create an .eslintrc.json file in your project’s root directory and configure ESLint with the desired rules and settings. Here’s a basic example:

{
"env": {
"node": true
},
"plugins": ["security"],
"rules": {
"security/detect-buffer-noassert": "error",
"security/detect-child-process": "error",
"security/detect-disable-mustache-escape": "error",
"security/detect-eval-with-expression": "error",
"security/detect-new-buffer": "error",
"security/detect-no-csrf-before-method-override": "error",
"security/detect-non-literal-fs-filename": "error",
"security/detect-non-literal-regexp": "error",
"security/detect-non-literal-require": "error",
"security/detect-object-injection": "error",
"security/detect-possible-timing-attacks": "error",
"security/detect-pseudoRandomBytes": "error",
"security/detect-unsafe-regex": "error"
}
}

This example configures ESLint with rules from eslint-plugin-security to detect potential security issues related to buffer handling, child processes, code injection, file system operations, and more. Customize the rules based on your project’s specific requirements and security considerations.

Now, run ESLint with the security linter rules enabled against your Node.js project files. Use the following command to perform the lint:

npx eslint .

This command will lint all JavaScript files in your project directory and display any security-related warnings or errors.

To ensure security linters are consistently used, consider integrating them into your development workflow. For example, you can configure ESLint to run automatically on file changes or as part of your continuous integration (CI) pipeline. You can use tools like pre-commit hooks or CI/CD systems to enforce linting before code is committed or deployed.

When the security linter detects security-related issues in your code, review the reported warnings and errors. Take appropriate action to fix or mitigate the identified vulnerabilities. Refactor your code, apply security best practices, and follow the linter’s recommendations to ensure your codebase is secure.

10. Setup Logging and Monitoring

Adding logging and monitoring to your Node.js application is crucial for protecting and ensuring the stability of your app. Here are the steps to implement logging and monitoring:

10.1 — Choose a Logging Framework

Select a logging framework that suits your requirements. Some popular options for Node.js applications include Winston, Bunyan, and Pino. Install the chosen logging framework using npm:

npm install winston

10.2 — Configure Logging

Set up logging configurations according to your needs. This includes specifying log levels, log formats, log destinations (console, file, database, etc.), and log rotation policies. Configure the logging framework you’ve chosen based on its documentation. Here’s a basic example using Winston:

const winston = require('winston');

// Configure logger
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'app.log' })
]
});

10.3 — Implement Logging

Place logging statements strategically throughout your codebase to capture relevant events, errors, or other important information. Use the logger instance created in the previous step to log messages:

// Log an info message
logger.info('Application started');

// Log an error
logger.error('An error occurred', { error: err });

10.4 — Set Up Monitoring Tools

Implement a monitoring solution to track the health, performance, and potential issues of your Node.js application. Popular monitoring tools include Prometheus, Grafana, New Relic, and Datadog. Follow the documentation of the chosen tool to install and configure it for your application.

10.5 — Instrument Your Code

Add monitoring instrumentation to your application by instrumenting important components, endpoints, or functions. This typically involves adding metrics, timers, and error reporting. Use the monitoring library or agent provided by your chosen monitoring tool.

// Example using Prometheus client library
const prometheus = require('prom-client');

// Define a counter metric
const requestsCounter = new prometheus.Counter({
name: 'app_requests_total',
help: 'Total number of requests',
});

// Instrument a request handler
app.get('/api/:id', (req, res) => {
// Increment requests counter
requestsCounter.inc();

// ... your code ...

res.send('Response');
});

10.6 — Set Up Alerting

Configure alerts based on defined thresholds or conditions to get notified when anomalies or critical events occur. Configure alert channels such as email, SMS, or integration with incident management tools.

10.7 — Monitor Logs and Metrics

Continuously monitor your logs and metrics to gain insights into the health and performance of your Node.js application. Set up log aggregation systems like ELK Stack (Elasticsearch, Logstash, Kibana), Splunk, or Graylog to collect and analyze logs. Use the monitoring tool’s dashboard to visualize metrics and monitor application behavior.

10.8 — React to Alerts

Regularly review alerts and take appropriate actions when triggered. Investigate the cause of issues, troubleshoot, and resolve them promptly to ensure the stability and security of your Node.js application.

Kudos! You have completed learning the top 10 security best practices to secure Node.js applications. Now go ahead and start implementing the above security measures in your current or upcoming projects.

If you enjoyed reading this article and have found it useful, then please give it a clap, share it with your friends, and follow me to get more updates on my upcoming articles. You can connect with me on LinkedIn. Or, you can visit my official website: tararoutray.com to know more about me.

Level Up Coding

Thanks for being a part of our community! Before you go:

🚀👉 Join the Level Up talent collective and find an amazing job


Top 10 Best Practices To Secure Node.js Apps in Production was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Tara Prasad Routray

Learn how to safeguard your Node.js applications against malicious users and ensure the uninterrupted, seamless operation of your app.

In today’s interconnected digital landscape, ensuring the security of web applications is of utmost importance. Node.js, with its efficient and scalable runtime environment, has become a popular choice for building server-side applications. However, as Node.js applications are deployed into production environments, they become potential targets for cyber threats and attacks. Therefore, it is vital to implement robust security measures to protect these applications and the sensitive data they handle.

This article explores the top 10 best practices to secure Node.js apps in production. By following these practices, developers, and system administrators can fortify their Node.js applications against common vulnerabilities and safeguard them from potential exploits. From keeping the runtime environment up-to-date to implementing secure authentication and encryption, these best practices cover a wide range of security considerations.

By adhering to these recommendations, developers can ensure that their Node.js applications are resilient and protected, providing users with a secure and reliable experience. Whether you are building a small-scale web application or a large enterprise-level system, incorporating these security practices into your development process will significantly enhance the security posture of your Node.js apps.

In the following sections, we will delve into each best practice in detail, exploring the rationale behind it and providing practical guidance on its implementation. By the end of this article, you will have a comprehensive understanding of the essential security measures to apply when deploying Node.js applications in production environments.

Let’s dive into the top 10 best practices to secure your Node.js apps and fortify them against potential threats, ensuring the integrity, confidentiality, and availability of your valuable data.

Top 10 Essential Measures for Ensuring Security in Node.js Applications

  1. Restrict SQL Injection Attacks
  2. Restrict XSS (Cross-Site Scripting) Attacks
  3. Restrict DOS (Denial-of-Service) Attacks
  4. Restrict CSRF (Cross-Site Request Forgery) Attacks
  5. Enable HTTP Security Headers
  6. Implement Robust Authentication
  7. Scan For Vulnerable Dependencies
  8. Limit Request Payload Size
  9. Use Security Linters
  10. Setup Logging and Monitoring

1. Restrict SQL Injection Attacks

SQL injection attacks are a common and critical vulnerability that can be exploited to gain unauthorized access to a database or manipulate its contents. Fortunately, there are several effective measures you can take to restrict SQL injection attacks in your Node.js application. Let’s explore some best practices:

1.1 — Parameterized Queries

Utilize parameterized queries or prepared statements when interacting with the database. Parameterized queries separate SQL logic from user-supplied data, preventing malicious input from altering the structure of the SQL query. This technique ensures that user inputs are treated as data values rather than executable code.

Example using the mysql module:

const mysql = require('mysql');
const connection = mysql.createConnection({ /* connection details */ });

const query = 'SELECT * FROM users WHERE username = ? AND password = ?';
const values = ['admin', 'password123'];

connection.query(query, values, (error, results) => {
// Handle query results
});

1.2 — Input Validation and Sanitization

Implement input validation and sanitization techniques to ensure that user-supplied data meets the expected criteria. Use libraries like validator.js or Joi to validate input against specific data types, formats, or constraints. Additionally, sanitize user inputs to remove or escape any potentially harmful characters.

Example using the validator.js library:

const validator = require('validator');

const userInput = req.body.username;

if (validator.isAlphanumeric(userInput)) {
// Proceed with the query
} else {
// Reject the input or show an error message
}

1.3 — Object-Relational Mapping (ORM) Libraries

Consider using ORM libraries, such as Sequelize or Knex.js, which provide an abstraction layer for database operations. ORM libraries automatically handle parameterized queries and sanitize user inputs, reducing the risk of SQL injection vulnerabilities.

Example using Sequelize:

const Sequelize = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', { /* connection details */ });

const User = sequelize.define('user', {
username: Sequelize.STRING,
password: Sequelize.STRING
});

User.findOne({ where: { username: userInput } })
.then(user => {
// Handle the query result
})
.catch(error => {
// Handle errors
});

1.4 — Stored Procedures

Consider using stored procedures provided by your database management system. Stored procedures encapsulate SQL logic within the database itself, reducing the risk of SQL injection attacks. By calling stored procedures with sanitized parameters, you can mitigate SQL injection vulnerabilities.

1.5 — The Least Privilege Principle

Follow the principle of least privilege when configuring database access for your Node.js application. Create a separate database user with the minimum required privileges necessary for the application to operate successfully. Restrict the user’s permissions to only execute the required queries and prevent direct access to sensitive database operations.

1.6 — Regular Updates and Security Audits

Stay up-to-date with the latest security patches and updates for your database management system. Regularly review the security configuration and conduct security audits to identify any potential vulnerabilities. Stay informed about common SQL injection techniques and new attack vectors to proactively protect your application.

2. Restrict XSS (Cross-Site Scripting) Attacks

XSS (Cross-Site Scripting) attacks pose a significant security risk to web applications, including those built with Node.js. These attacks involve injecting malicious scripts into web pages, which can lead to unauthorized data access, session hijacking, or other malicious activities. To restrict XSS attacks in your Node.js application, consider implementing the following best practices:

2.1 — Input Validation and Sanitization

Implement strict input validation and sanitization to prevent untrusted data from being rendered as active content in the browser. Use libraries like validator.js or DOMPurify to sanitize user inputs, removing or escaping any potentially malicious code or characters.

Example using DOMPurify:

const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');

const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);

const userInput = req.body.comment;

const sanitizedInput = DOMPurify.sanitize(userInput);

2.2 — Content Security Policy (CSP)

Implement a Content Security Policy (CSP) to restrict the execution of untrusted scripts in the browser. CSP defines a set of rules that specify which types of content can be loaded and executed on a web page. By whitelisting trusted sources for scripts, stylesheets, and other resources, you can effectively mitigate XSS attacks.

Example of setting CSP headers in Express.js:

const express = require('express');
const app = express();

app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self' example.com");
next();
});

2.3 — Templating Engines

If you are using a templating engine, ensure that it automatically escapes user-generated content by default. Popular templating engines like Handlebars and EJS have built-in mechanisms to prevent XSS attacks by escaping dynamic content. Make sure to enable auto-escaping and review your templates to ensure all user inputs are properly escaped.

Example using EJS:

const ejs = require('ejs');
const template = `<h1><%= user.name %></h1>`;

const data = {
name: `<script>alert('XSS Attack');</script>`
};

const rendered = ejs.render(template, { user: data }, { escape: true });

2.4 — HTTP-only Cookies

Utilize HTTP-only cookies to mitigate the risk of XSS attacks targeting session data. By setting the httpOnly flag when creating cookies, you ensure that they can only be accessed by the server and are not accessible to client-side scripts. This prevents attackers from stealing or manipulating sensitive session information.

Example using the cookie library:

const cookie = require('cookie');
const express = require('express');
const app = express();

app.get('/', (req, res) => {
const sessionData = {
user_id: 123,
username: 'john'
};

const sessionCookie = cookie.serialize('session', JSON.stringify(sessionData), {
httpOnly: true,
secure: true, // Enable this if using HTTPS
sameSite: 'strict'
});

res.setHeader('Set-Cookie', sessionCookie);
res.send('Hello World');
});

2.5 — Regular Updates and Security Audits

Stay up-to-date with security patches for the libraries and frameworks you use in your Node.js application. Keep an eye on security advisories and updates from the Node.js community. Regularly review and audit your codebase to identify and fix any potential XSS vulnerabilities.

3. Restrict DOS (Denial-of-Service) Attacks

Restricting Denial-of-Service (DoS) attacks in Node.js requires implementing measures to mitigate excessive resource consumption and ensure the availability of your application even under attack. While it may not be possible to eliminate the risk of DoS attacks, you can take several steps to minimize their impact. Here are some best practices to help you restrict DoS attacks in your Node.js application:

3.1 — Implement Rate Limiting

Enforce rate limiting to restrict the number of requests a client can make within a specific time frame. This prevents an individual client from overwhelming your application with a flood of requests. Consider using libraries like express-rate-limit or limiter to implement rate limiting based on IP addresses, request headers, or other criteria.

Example using express-rate-limit middleware:

const express = require('express');
const rateLimit = require('express-rate-limit');
const app = express();

const limiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100 // Limit each IP to 100 requests per minute
});

app.use(limiter);

3.2 — Use Caching

Leverage caching mechanisms to reduce the load on your application and improve its resilience against DoS attacks. Implement caching at different layers, such as in-memory caches like Redis, or external caching services like Memcached or CDN (Content Delivery Network) solutions. Caching can help serve static or frequently accessed data without invoking resource-intensive operations.

3.3 — Implement Request Validation and Filtering

Validate and filter incoming requests to discard malicious or malformed requests before they reach resource-intensive parts of your application. Utilize validation libraries like Joi, or custom request validation middleware to ensure that requests meet the required criteria. Reject or ignore requests that do not adhere to expected patterns, reducing the processing overhead.

3.4 — Enable Keep-Alive Connections

Configure your Node.js server to enable Keep-Alive connections. Keep-Alive allows multiple requests to be served over a single TCP connection, reducing the overhead of establishing new connections for each request. This helps conserve server resources and mitigate the impact of connection-based DoS attacks.

Example using the http module:

const http = require('http');

const server = http.createServer((req, res) => {
// Request handling logic
});

server.keepAliveTimeout = 60000; // Set the keep-alive timeout to 60 seconds

3.5 — Implement Timeouts

Set appropriate timeouts for request and response handling to limit the impact of slow or stalled requests. Use the timeout option available in libraries like Express.js or directly set timeout values for specific operations. By terminating long-running requests, you can free up resources and ensure that your application remains responsive.

Example using Express.js:

const express = require('express');
const app = express();

app.use((req, res, next) => {
req.setTimeout(5000); // Set request timeout to 5 seconds
res.setTimeout(5000); // Set response timeout to 5 seconds
next();
});

// Rest of your application code

3.6 — Distributed Denial-of-Service (DDoS) Mitigation

Consider using DDoS mitigation services (like Cloudflare) to protect your application from large-scale DDoS attacks. These services employ various techniques such as traffic analysis, rate limiting, and IP filtering to identify and mitigate DDoS attack traffic before it reaches your application.

3.7 — Network and Infrastructure Hardening

Implement network and infrastructure-level measures to protect your Node.js application from DoS attacks. This includes setting up firewalls, intrusion detection and prevention systems (IDPS), load balancers, and proper network segmentation. Regularly monitor network traffic and implement anomaly detection mechanisms to identify and respond to potential attacks.

4. Restrict CSRF (Cross-Site Request Forgery) Attacks

Restricting Cross-Site Request Forgery (CSRF) attacks in Node.js involves implementing countermeasures that prevent malicious actors from exploiting the trust between a user and a website to perform unauthorized actions on behalf of the user. Here are some best practices to help you restrict CSRF attacks in your Node.js application:

4.1 — Implement CSRF Tokens

Utilize CSRF tokens to validate the authenticity of requests. Generate a unique CSRF token for each user session and include it in forms or as a custom header in AJAX requests. On the server side, validate the received token with the one stored in the user’s session to ensure it matches.

Example using the csurf middleware:

const express = require('express');
const csrf = require('csurf');
const app = express();

// Enable CSRF protection for all routes
app.use(csrf({ cookie: true }));

// Include the CSRF token in the response locals
app.use((req, res, next) => {
res.locals.csrfToken = req.csrfToken();
next();
});

// Rest of your application code

4.2 — Set the “SameSite” Attribute

Set the “SameSite” attribute for cookies to control when they are sent with cross-site requests. By setting it to “Strict” or “Lax,” you can restrict the transmission of cookies to only same-site requests, mitigating the risk of CSRF attacks.

Example using the cookie library in Express.js:

const cookie = require('cookie');
const express = require('express');
const app = express();

app.use((req, res, next) => {
const csrfToken = req.csrfToken();

// Set the CSRF token as a cookie with the SameSite attribute
res.setHeader('Set-Cookie', cookie.serialize('csrfToken', csrfToken, {
sameSite: 'Strict',
secure: true, // Enable this if using HTTPS
httpOnly: true
}));

next();
});

// Rest of your application code

4.3 — Verify Origin and Referrer Headers

Check the Origin and Referer headers of incoming requests to ensure they match the expected values. Validate that the request originates from an authorized domain and is not a cross-origin request. However, note that the Referer header can be spoofed, so relying solely on it is not sufficient.

4.4 — Use Anti-CSRF Libraries

Consider using anti-CSRF libraries like csurf, helmet, or csurf-elixir to simplify the implementation of CSRF protection. These libraries handle token generation, validation, and integration with popular frameworks, making it easier to secure your Node.js application against CSRF attacks.

4.5 — Apply Strict CORS Policies

Implement strict Cross-Origin Resource Sharing (CORS) policies to control which origins are allowed to make cross-origin requests to your application. Use the cors middleware or set appropriate headers to specify the allowed origins, methods, and headers. This helps prevent unauthorized cross-origin requests that could lead to CSRF attacks.

Example using the cors middleware:

const express = require('express');
const cors = require('cors');
const app = express();

// Enable CORS with specific options
app.use(cors({
origin: 'https://www.example.com',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization']
}));

// Rest of your application code

5. Enable HTTP Security Headers

To enable HTTP security headers in a Node.js application, you can use the helmet package. Helmet is a middleware that helps secure your application by setting various HTTP headers. Here’s how you can enable HTTP security headers using Helmet in Node.js:

Install the helmet package by running the following command in your Node.js project directory:

npm install helmet

Require the helmet package at the top of your Node.js file:

const helmet = require('helmet');

Use the helmet middleware in your Express.js application:

const express = require('express');
const app = express();

// Use helmet middleware
app.use(helmet());

By default, Helmet sets several security headers. However, you can customize the headers according to your requirements. For example, to enable the Content-Security-Policy header, you can use the helmet.contentSecurityPolicy() middleware:

app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'"],
},
})
);

In the above example, we set the defaultSrc to allow resources from the same origin (‘self’), and we allow ‘unsafe-inline’ and ‘unsafe-eval’ for JavaScript (scriptSrc) and inline styles (styleSrc). You can adjust these directives according to your application’s needs.

6. Implement Robust Authentication

Implementing robust authentication in a Node.js application involves several steps. Here’s a high-level overview of the process:

6.1 — Choose an Authentication Strategy

There are various authentication strategies you can choose from, such as session-based authentication, token-based authentication (e.g., JWT), or OAuth. Consider the requirements of your application and choose the strategy that best fits your needs.

6.2 — Securely Store User Credentials

When users register, securely store their credentials in a database. Hash passwords using a strong hashing algorithm, such as bcrypt or Argon2, to protect against data breaches.

6.3 — Create User Registration and Login Routes

Set up routes for user registration and login. Validate user input and authenticate users using the chosen authentication strategy. Generate and issue authentication tokens or session cookies as needed.

6.4 — Implement Password Reset and Change Password Functionality

Allow users to reset their passwords if they forget them or change their passwords if needed. This typically involves sending password reset emails with a secure token and providing routes to handle the password reset process.

6.5 — Implement Middleware for Authentication

Create middleware that checks the authentication status of incoming requests. This middleware should validate the authentication token or session and grant access to protected routes only to authenticated users.

6.6 — Implement Authorization

Define user roles and permissions to control access to different parts of your application. Implement authorization middleware that checks if a user has the necessary permissions to access a specific resource or perform an action.

6.7 — Secure Sensitive Data

If your application handles sensitive data, ensure it’s protected. Use encryption, such as HTTPS/TLS, to secure data in transit. Encrypt sensitive data at rest, for example, by using a secure database or encrypting specific fields.

7. Scan For Vulnerable Dependencies

To scan for vulnerable dependencies in a Node.js application, you can use a package vulnerability scanner. One popular tool for this purpose is the npm audit command, which is built into the npm package manager. Here’s how you can use npm audit to scan for vulnerable dependencies:

Open your terminal or command prompt and navigate to your Node.js project directory. Run the following command to perform a vulnerability scan:

npm audit

The npm audit command will analyze your project’s dependencies and provide a report on any known vulnerabilities. It will categorize the vulnerabilities as “high,” “moderate,” or “low” severity based on their impact. It will also suggest actions to fix the vulnerabilities.

Review the output of the npm audit command. It will list the vulnerable packages, their versions, and a description of the vulnerability. It will also suggest an update or provide instructions on how to fix the vulnerability.

To automatically fix the vulnerabilities that have known updates, you can run the following command:

npm audit fix

This command will attempt to update vulnerable packages to their latest versions, applying fixes where available. However, please note that this command may not be able to fix all vulnerabilities, particularly if there are breaking changes or if the maintainers of the packages have not released patches.

After running npm audit fix, review the changes made to your project’s dependencies. Verify that the fixes did not introduce any compatibility issues or break your application’s functionality. If you encounter issues, you may need to manually update or replace certain packages to resolve the vulnerabilities.

It’s important to regularly perform vulnerability scans on your dependencies and keep them up to date to minimize the risk of potential security breaches. Additionally, consider using automated vulnerability scanning tools, such as Snyk, npm audit-ci, or retire.js, for more comprehensive and continuous monitoring of your project’s dependencies. These tools can provide detailed reports and notifications about vulnerabilities and suggest remediation steps.

8. Limit Request Payload Size

To limit the request payload size in a Node.js application, you can use middleware to intercept incoming requests and enforce a size limit. Here’s an example using the express framework:

Install the express package if you haven’t already:

npm install express

Require the necessary modules and create an instance of the express application:

const express = require('express');
const app = express();

Use the express.json() middleware to parse incoming JSON payloads:

app.use(express.json());

Define a custom middleware function to limit the request payload size. This middleware will check the Content-Length header of the request and reject the request if it exceeds the specified size limit:

const limitPayloadSize = (req, res, next) => {
const MAX_PAYLOAD_SIZE = 1024 * 1024; // 1MB

if (req.headers['content-length'] && parseInt(req.headers['content-length']) > MAX_PAYLOAD_SIZE) {
return res.status(413).json({ error: 'Payload size exceeds the limit' });
}

next();
}

In this example, the maximum payload size is set to 1MB (1024 * 1024 bytes), but you can adjust it to your desired size. Use the limitPayloadSize middleware in your application to limit the request payload size:

app.use(limitPayloadSize);

With this implementation, any incoming requests with a payload size exceeding the defined limit will receive a 413 Payload Too Large response.

Keep in mind that this approach only limits the size of JSON payloads. If you’re handling other types of payloads, such as file uploads, you may need to employ additional middleware or techniques specific to those scenarios.

9. Use Security Linters

Using security linters in Node.js is an effective way to identify and prevent common security vulnerabilities in your codebase. Here’s how you can incorporate security linters into your Node.js development workflow:

There are several security linters available for Node.js projects. One popular option is eslint-plugin-security, which is an ESLint plugin specifically designed to detect security issues. Install it by running the following command:

npm install eslint eslint-plugin-security --save-dev

If you haven’t already set up ESLint for your Node.js project, create an .eslintrc.json file in your project’s root directory and configure ESLint with the desired rules and settings. Here’s a basic example:

{
"env": {
"node": true
},
"plugins": ["security"],
"rules": {
"security/detect-buffer-noassert": "error",
"security/detect-child-process": "error",
"security/detect-disable-mustache-escape": "error",
"security/detect-eval-with-expression": "error",
"security/detect-new-buffer": "error",
"security/detect-no-csrf-before-method-override": "error",
"security/detect-non-literal-fs-filename": "error",
"security/detect-non-literal-regexp": "error",
"security/detect-non-literal-require": "error",
"security/detect-object-injection": "error",
"security/detect-possible-timing-attacks": "error",
"security/detect-pseudoRandomBytes": "error",
"security/detect-unsafe-regex": "error"
}
}

This example configures ESLint with rules from eslint-plugin-security to detect potential security issues related to buffer handling, child processes, code injection, file system operations, and more. Customize the rules based on your project’s specific requirements and security considerations.

Now, run ESLint with the security linter rules enabled against your Node.js project files. Use the following command to perform the lint:

npx eslint .

This command will lint all JavaScript files in your project directory and display any security-related warnings or errors.

To ensure security linters are consistently used, consider integrating them into your development workflow. For example, you can configure ESLint to run automatically on file changes or as part of your continuous integration (CI) pipeline. You can use tools like pre-commit hooks or CI/CD systems to enforce linting before code is committed or deployed.

When the security linter detects security-related issues in your code, review the reported warnings and errors. Take appropriate action to fix or mitigate the identified vulnerabilities. Refactor your code, apply security best practices, and follow the linter’s recommendations to ensure your codebase is secure.

10. Setup Logging and Monitoring

Adding logging and monitoring to your Node.js application is crucial for protecting and ensuring the stability of your app. Here are the steps to implement logging and monitoring:

10.1 — Choose a Logging Framework

Select a logging framework that suits your requirements. Some popular options for Node.js applications include Winston, Bunyan, and Pino. Install the chosen logging framework using npm:

npm install winston

10.2 — Configure Logging

Set up logging configurations according to your needs. This includes specifying log levels, log formats, log destinations (console, file, database, etc.), and log rotation policies. Configure the logging framework you’ve chosen based on its documentation. Here’s a basic example using Winston:

const winston = require('winston');

// Configure logger
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'app.log' })
]
});

10.3 — Implement Logging

Place logging statements strategically throughout your codebase to capture relevant events, errors, or other important information. Use the logger instance created in the previous step to log messages:

// Log an info message
logger.info('Application started');

// Log an error
logger.error('An error occurred', { error: err });

10.4 — Set Up Monitoring Tools

Implement a monitoring solution to track the health, performance, and potential issues of your Node.js application. Popular monitoring tools include Prometheus, Grafana, New Relic, and Datadog. Follow the documentation of the chosen tool to install and configure it for your application.

10.5 — Instrument Your Code

Add monitoring instrumentation to your application by instrumenting important components, endpoints, or functions. This typically involves adding metrics, timers, and error reporting. Use the monitoring library or agent provided by your chosen monitoring tool.

// Example using Prometheus client library
const prometheus = require('prom-client');

// Define a counter metric
const requestsCounter = new prometheus.Counter({
name: 'app_requests_total',
help: 'Total number of requests',
});

// Instrument a request handler
app.get('/api/:id', (req, res) => {
// Increment requests counter
requestsCounter.inc();

// ... your code ...

res.send('Response');
});

10.6 — Set Up Alerting

Configure alerts based on defined thresholds or conditions to get notified when anomalies or critical events occur. Configure alert channels such as email, SMS, or integration with incident management tools.

10.7 — Monitor Logs and Metrics

Continuously monitor your logs and metrics to gain insights into the health and performance of your Node.js application. Set up log aggregation systems like ELK Stack (Elasticsearch, Logstash, Kibana), Splunk, or Graylog to collect and analyze logs. Use the monitoring tool’s dashboard to visualize metrics and monitor application behavior.

10.8 — React to Alerts

Regularly review alerts and take appropriate actions when triggered. Investigate the cause of issues, troubleshoot, and resolve them promptly to ensure the stability and security of your Node.js application.

Kudos! You have completed learning the top 10 security best practices to secure Node.js applications. Now go ahead and start implementing the above security measures in your current or upcoming projects.

If you enjoyed reading this article and have found it useful, then please give it a clap, share it with your friends, and follow me to get more updates on my upcoming articles. You can connect with me on LinkedIn. Or, you can visit my official website: tararoutray.com to know more about me.

Level Up Coding

Thanks for being a part of our community! Before you go:

🚀👉 Join the Level Up talent collective and find an amazing job


Top 10 Best Practices To Secure Node.js Apps in Production was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Tara Prasad Routray


Print Share Comment Cite Upload Translate Updates
APA

Tara Prasad Routray | Sciencx (2023-06-04T19:38:25+00:00) Top 10 Best Practices To Secure Node.js Apps in Production. Retrieved from https://www.scien.cx/2023/06/04/top-10-best-practices-to-secure-node-js-apps-in-production/

MLA
" » Top 10 Best Practices To Secure Node.js Apps in Production." Tara Prasad Routray | Sciencx - Sunday June 4, 2023, https://www.scien.cx/2023/06/04/top-10-best-practices-to-secure-node-js-apps-in-production/
HARVARD
Tara Prasad Routray | Sciencx Sunday June 4, 2023 » Top 10 Best Practices To Secure Node.js Apps in Production., viewed ,<https://www.scien.cx/2023/06/04/top-10-best-practices-to-secure-node-js-apps-in-production/>
VANCOUVER
Tara Prasad Routray | Sciencx - » Top 10 Best Practices To Secure Node.js Apps in Production. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/06/04/top-10-best-practices-to-secure-node-js-apps-in-production/
CHICAGO
" » Top 10 Best Practices To Secure Node.js Apps in Production." Tara Prasad Routray | Sciencx - Accessed . https://www.scien.cx/2023/06/04/top-10-best-practices-to-secure-node-js-apps-in-production/
IEEE
" » Top 10 Best Practices To Secure Node.js Apps in Production." Tara Prasad Routray | Sciencx [Online]. Available: https://www.scien.cx/2023/06/04/top-10-best-practices-to-secure-node-js-apps-in-production/. [Accessed: ]
rf:citation
» Top 10 Best Practices To Secure Node.js Apps in Production | Tara Prasad Routray | Sciencx | https://www.scien.cx/2023/06/04/top-10-best-practices-to-secure-node-js-apps-in-production/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.