Safeguard
Application Security•

How do you secure a Node.js application? A production checklist

Securing Node.js mostly means securing what runs in it: dependencies, input, HTTP timeouts and process permissions. A checklist from the Node.js docs.

Safeguard Security Team
5 min read

Securing a Node.js application is mostly about the code it runs, not the runtime itself. Lock down dependencies with lockfiles and npm ci, validate untrusted input, set HTTP timeouts behind a reverse proxy, never expose the inspector, and restrict what the process may touch. The official Node.js guide is the baseline.

Where does Node.js draw the line on responsibility?

The official security guide starts with an important distinction. The Node.js threat model defines what counts as a vulnerability in Node.js itself. Several topics in the guide, including denial of service from request contents, prototype pollution and malicious dependencies, are not vulnerabilities in the runtime, because Node.js treats the code and input it is given as trusted. They are still serious application-level threats, and they are yours to handle.

Are dependencies the biggest risk?

The guide calls malicious or compromised dependencies one of the most critical application-level risks. Any package in a Node.js process can reach the network and the file system, and can load more code. Its examples are blunt: a hijacked maintainer account on a logging library ships a minor version that sends environment variables to a remote server, or a typosquatted package runs a postinstall script that uploads SSH keys.

Mitigations the guide lists:

  • Pin dependency versions to exact, immutable versions. It notes that pinning a direct dependency does not pin its transitive ones, which is why lockfiles matter.
  • Use lockfiles, and install with npm ci, which fails if the lockfile and package.json disagree instead of quietly ignoring the lockfile.
  • Block install scripts by setting ignore-scripts to true in npm config.
  • Run npm audit in CI for known vulnerabilities.
  • Consider a release cooldown. With the min-release-age setting (npm 11.10.0 or later), npm refuses packages newer than a number of days. The guide says most compromised packages are removed within hours, so even one day avoids many short-lived attacks. You can override it for an urgent security fix.
  • Check package.json for typos in package names, and remember the source on GitHub may not match what was published.

What about untrusted input?

Prototype pollution is the JavaScript-specific one. If code merges untrusted JSON into an object without care, a payload using the special prototype property can add attributes to every object in the process. The guide's mitigations: avoid insecure recursive merges, validate external requests against a JSON schema, create plain lookup objects with Object.create(null), and check ownership with Object.hasOwn.

Timing attacks are the other classic. Comparing a secret with ordinary string equality leaks information through response time. The guide points to the crypto module's timingSafeEqual and to scrypt for passwords.

How do you keep the HTTP server from falling over?

The guide notes a denial of service does not need a malicious request, since a buggy client can cause one. Its advice:

  • Put a reverse proxy in front for caching, load balancing and filtering.
  • Set server timeouts, particularly headersTimeout, requestTimeout, timeout and keepAliveTimeout, so slow clients such as Slowloris-style senders cannot hold connections open.
  • Limit open sockets per host and in total.
  • Handle socket errors. The docs show a server without an error handler that can crash on a bad connection.

For request smuggling, where a proxy and Node.js read an ambiguous request differently, the guide says not to enable the insecure HTTP parser option and to normalize ambiguous requests at the front end.

Can you limit what the process can do?

Yes, with the permission model. When enabled, it lets you allow or deny file system reads and writes, network access, child process creation and native addons. The guide says this can contain the impact of a compromised dependency because even trusted code is stopped outside the permissions you grant. Check the permission docs for current flags.

Also: do not run the inspector in production, since DNS rebinding can reach it; run npm publish with a dry run first so you do not ship secrets; and avoid experimental features in production.

A constructed example

An API merges a request body into a settings object with a hand-written deep merge, and a dependency three levels down gets a malicious patch release. With a lockfile and npm ci, the CI build does not pick up the patch release until someone reviews the lockfile change. With a JSON schema on the endpoint, the polluting payload is rejected before the merge. With the permission model, even a hostile package cannot open an outbound connection that the process was never granted.

How to check or apply this

  1. Commit the lockfile, switch CI to npm ci, and review lockfile diffs.
  2. Turn off install scripts by default and allow them per package where needed.
  3. Add a JSON schema to every endpoint that accepts a body.
  4. Set the four HTTP timeouts and put a proxy in front.
  5. Trial the permission model in staging and record which access the app really needs.
  6. Scan the dependency tree and fix what is reachable first. Safeguard's CLI scans dependencies, and reachability analysis ranks findings by whether your code calls the vulnerable path.

Quick check

Does pinning a dependency version make me safe from supply chain attacks?

Not fully. The Node.js guide notes that pinning a direct dependency does not pin its transitive dependencies. Use a lockfile and npm ci so the whole tree is fixed.

Is prototype pollution a Node.js vulnerability?

Per the Node.js threat model, when it depends on attacker-controlled input to application code it is not a flaw in Node.js core, but it is a serious application and library risk you must defend against.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.