Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

8 elements of securing Node.js applications

Introduction to the Node.js reference architecture, Part 9

August 9, 2022
Lucas Holmquist
Related topics:
ContainersKubernetesNode.jsSecure Coding
Related products:
Red Hat build of Node.jsRed Hat OpenShift Container Platform

Share:

    Making your Node.js applications secure is an essential part of the development of Node.js modules and applications. Security practices apply to both the code itself and your software development process. This installment of the ongoing Node.js reference architecture series focuses on some of the key security elements that JavaScript developers should address.

    Follow the series:

    • Part 1: Overview of the Node.js reference architecture
    • Part 2: Logging in Node.js
    • Part 3: Code consistency in Node.js
    • Part 4: GraphQL in Node.js
    • Part 5: Building good containers
    • Part 6: Choosing web frameworks
    • Part 7: Code coverage
    • Part 8: Typescript
    • Part 9: Securing Node.js applications
    • Part 10: Accessibility
    • Part 11: Typical development workflows
    • Part 12: npm development
    • Part 13: Problem determination
    • Part 14: Testing
    • Part 15: Transaction handling
    • Part 16: Load balancing, threading, and scaling
    • Part 17: CI/CD best practices in Node.js
    • Part 18: Wrapping up

    This article covers eight key elements of building security into your software development process to make your Node.js applications and modules robust:

    1. Choosing dependencies
    2. Managing access and content of public and private data stores such as npm and GitHub
    3. Writing defensive code
    4. Limiting required execution privileges
    5. Support for logging and monitoring
    6. Externalizing secrets
    7. Maintaining a secure and up-to-date foundation for deployed applications
    8. Maintaining individual modules

    Although this is not necessarily an exhaustive list, these are commonly the focus of the Red Hat and IBM teams.

    1. Choosing third-party dependencies

    Most Node.js applications and modules have third-party dependencies, many of which contain security vulnerabilities. Although open source teams usually fix the vulnerabilities soon after discovery, there are still gaps in time before an application developer learns about the vulnerability and puts the fixed library into production. Attackers might exploit the compromised program during those times. So it is important to choose dependencies carefully and regularly evaluate if they remain the right choices for you.

    A couple of helpful tips in this area are:

    • Determine that a dependency is necessary before integrating it into your application. Is using the modules instead of your code saving development and maintenance time?
    • Avoid code one-liners.
    • If you have a choice of dependencies, use one that has only a few or no dependencies of its own.
    • Choose dependencies that already have a high level of usage based on statistics, such as GitHub stars and npm. These tend to be maintained well.

    Find more in-depth guidance on managing dependencies in the reference architecture's choosing and vetting dependencies section.

    2. Managing access and content of public and private data stores

    Modern development flows often use public and private data stores, including npm and GitHub. We recommend the following management practices:

    • Enable two-factor authentication (2FA) to ensure the integrity of the committed code and published assets. GitHub, for instance, now requires a developer who logs in to verify their identity through a code sent to their device.
    • Use files such as .npmignore and .gitignore to avoid accidentally publishing secrets. These are hidden files consulted by programs (npm and Git, respectively). If you list a file with your secrets in one of these hidden files, npm and Git will never check it into the source repository. Of course, you must have a separate process to manage the secrets. There are many services available to help you.

    A .npmrc file is often needed for npm installations, particularly if you have private modules. Avoid leaking information in the .npmrc file when building containers by using one of these options:

    • Use two-stage builds, where you build one image with all the tools for the application and a second to create a stripped-down image. In addition to saving memory and disk space, the two-stage build allows you to omit the .npmrc file from the final image that goes into production.
    • Avoid adding the secrets to any image in the build process. Instead, you can securely mount secrets into containers during the build process, as explained in the article How to sneak secrets into your containers. In particular, Buildah has built-in functions to make it easier to mount files with secrets.
    • The least preferred method:  Delete the .npmrc file from the final image and compress images to flatten layers.

    3. Writing defensive code

    Secure coding often calls for special training and cannot be summarized in simple precepts. Nevertheless, you can eliminate many common vulnerabilities by following the recommendations in this section. There is a more extensive list in the Secure Development Process section of the reference architecture.

    Avoid global state

    Using global variables makes it easy to leak information between requests accidentally. With global variables, data from one web visitor might be in memory when a second visitor sends a request. Potential impacts include corrupting the request or revealing private information to another visitor.

    Each request should encapsulate its data. If you need global data, such as statistics about the traffic you are handling, store it in an external database. This solution is preferable to global variables because the data in the database is persistent.

    Set the NODE_ENV environment variable to production

    Some packages consult the NODE_ENV environment variable to decide whether they need to lock things down or share less information. Therefore, setting the variable to production is the safest setting and should be used all the time. The application developer, not the package, should determine what information to display.

    Validate user input

    Unvalidated input can result in attacks such as command injection, SQL injection, and denial of service, disrupting your service and corrupting data. Always validate user input before implementing it within your application code. Make sure you validate input on the server even if you validate on the client side (browser or mobile application) because an attacker could send requests directly to the APIs without using the client.

    Include good exception handling

    Basic practices for handling exceptions include:

    • Check at a high level for missed exceptions and handle them gracefully. Make sure to have a default handler for Express and other web frameworks to avoid displaying errors with the stack trace to the visitor.
    • Listen to errors when using EventEmitters.
    • Check for errors passed into asynchronous calls.

    Avoid complex regular expressions

    Regular expressions help with text parsing tasks, such as ensuring that a visitor submitted their email address or phone number in an acceptable format or checking input for suspicious characters that could signal an attack. Unfortunately, if a regular expression is complex, it can take a long time to run. In fact, some regexes run essentially forever on certain kinds of text.

    Even worse, although your regular expression might operate reasonably under most input, a malicious attacker could provide content that triggers an endless run. The article Regular expression Denial of Service - ReDoS explains this type of vulnerability.

    The takeaway is to be careful about the complexity of any regular expression you use.  When checking text input, avoid regular expressions or use only simple ones that check for issues such as invalid characters.

    Limit the attack surface

    Some helpful ways to limit the available attack surface are:

    • Expose only the APIs needed to support the intended operations. For example, when using Express, remove any unnecessary routes.
    • Group all external endpoints under a prefix (i.e., /api). This makes it easier to expose only APIs intended to be external in the ingress configuration.
    • Don't rewrite paths to the root (/).
    • Use authentication to limit access. When possible, integrate an organizational identity and access control provider instead of implementing your own.

    4. Limiting required execution privileges

    Design your applications to run with the minimum privileges required. Ensure that your applications can run as a non-root user, especially when deployed within containers. The user and group under which the application runs should have access only to a minimal set of files and resources. For more container recommendations, check out part five of this series:  Building good containers.

    5. Support for logging and monitoring

    Logging sensitive or suspicious actions will make it easier for monitoring tools to collect and analyze the data. See the logging section of the reference architecture for recommended monitoring packages.

    6. Externalizing secrets

    Secrets (i.e., passwords) should be defined externally and made available to the application at runtime through secure means. Make sure you don't commit secrets in code repositories or build them into container images.

    The article GitOps secret management provides a good overview of the techniques and components used to manage externalized secrets. The article also refers to additional articles on the topic.

    More specific to Node.js deployments, consider using the dotenv package, which is popular among our team. We also contribute to kube-service-bindings to support the Service Binding Specification for Kubernetes.

    One of the leading tools for managing externalized secrets is node-vault. Teams involved in deployments with the IBM cloud find the IBM Cloud Secrets Manager Node.js SDK helpful.

    7. Maintaining a secure and up-to-date foundation for deployed applications

    A Node.js application is on top of several components. You must keep this foundation secure and up to date throughout your application's lifetime, even if no code changes within your application.

    The key elements include secure and up-to-date:

    • base container images
    • Node.js runtime
    • dependencies

    Based on the team's experience, here are some recommended tips:

    • Take advantage of container images that come with Node.js already bundled in. The maintainers usually release an update after fixing a CVE reported against the Node.js runtime or any other components within the container. This is one of the reasons the team members often use the ubi/nodejs container images.
    • If you build Node.js binaries into a base image, subscribe to and read the nodejs-sec mailing list. This low-volume mailing list provides advance notice of security releases and will give you the earliest warning to update your Node.js version.
    • If you use common dependencies across many projects, create a dependency image from which each project reads. While this centralization is suitable for build times, as outlined in the dependency image section of the reference architecture, it also helps reduce the total work required for dependency updates when shared across numerous projects.

    For a more exhaustive list of tips, check out the Secure Development Process section of the reference architecture.

    8. Maintaining individual modules

    When you maintain modules in GitHub, enable Snyk integration and review the pull requests it creates.

    It is also important to test and ensure the module runs and passes tests on the latest Long Term Support (LTS) version of Node.js. Automated testing reduces risk when Node.js security releases require updates.

    Coming next

    We cover new topics regularly as part of the Node.js reference architecture series. The next installment covers key questions that Node.js developers need to understand about accessibility.

    We invite you to visit the Node.js reference architecture repository on GitHub, where you will see the work we have done and look forward to future topics.

    To learn more about what Red Hat is up to on the Node.js front, check out our Node.js page.

    Last updated: January 10, 2024

    Related Posts

    • Install Node.js on Red Hat Enterprise Linux

    • Build your first application using Node.js with Red Hat Container Development Kit (CDK)

    • What's happening in the Node.js community

    • What enterprise developers need to know about security and compliance

    Recent Posts

    • More Essential AI tutorials for Node.js Developers

    • How to run a fraud detection AI model on RHEL CVMs

    • How we use software provenance at Red Hat

    • Alternatives to creating bootc images from scratch

    • How to update OpenStack Services on OpenShift

    What’s up next?

    10 tips for nodejs cheat sheet tile card

    Run secure and efficient Node.js applications on OpenShift and other container environments. This cheat sheet rounds up 10 tips to help you learn best practices and get up to speed quickly.

    Get the cheat sheet
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue