System theme
Node.js

Import built-in Node modules with the 'node:' protocol – why it matters

The 'node:' prefix prevents typosquatting attacks when importing core modules. Learn why this security improvement matters and how to migrate your code.

KK13 · 2 min read

Import built-in Node modules with the 'node:' protocol – why it matters

1. Background

The node: prefix was added to eliminate typosquatting when importing core modules. Developers often mistype module names like 'event' instead of 'events' or 'http2' instead of 'http', accidentally installing malicious packages that mimic official Node.js modules.

2. Syntax shift

  • ESM: Change import { createServer } from 'http'import { createServer } from 'node:http'
  • CommonJS: Change const http = require('http')const http = require('node:http')

3. Minimal working example

// server.mjs
import { createServer } from 'node:http';

const server = createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello from node:http!\n');
});

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

Run with: node server.mjs

4. What breaks without the prefix

Node resolves the name as an npm package, so import { createServer } from 'http' will:

  • Install a malicious 'http' package if it exists on npm
  • Lose ESLint/IDE hints that it's a built-in module
  • Create confusion between official and third-party modules

5. Security & tooling benefits

  • ESLint rule prefer-node-protocol: Flags missing prefix, encouraging correct imports
  • Static analyzers: Treat the module as trusted core code rather than external dependency
  • Explicit intent: Makes it clear to reviewers and teammates that you're using Node's built-in functionality
  • Prevention: Eliminates typosquatting attacks where malicious packages exploit common module name misspellings

6. Adoption checklist

  • Run npm audit: Check for existing vulnerable packages using incorrect imports
  • Update ESLint config: Add plugin:node/recommend and plugin:node/no-deprecated
  • Replace all require('…') of core modules: Use require('node:module-name') syntax
  • Verify tests still pass: Some test mocks might rely on the old import pattern
  • Document the change: Update contributing guide and README with new import conventions

Summary

The node: protocol is a security improvement that prevents typosquatting attacks and clarifies intent when using Node's built-in modules. While it's a simple syntax change, it has significant security implications and tooling benefits. Adoption is straightforward but important for maintaining security hygiene in Node.js projects.

:::warning Need to check Verify the exact version when node: protocol was introduced and confirm ESLint rule availability. :::

:::warning Need to check Check if there are any edge cases where the old import syntax might still work but could introduce security risks. :::

:::warning Need to check Investigate any migration challenges for large codebases transitioning to the new protocol. :::

References

  • Node.js documentation on module resolution
  • ESLint plugin configuration examples
  • npm security advisories related to typosquatting

Next in Node.js

Node.js Is Multi-Threaded: How libuv Runs Your Blocking Work

The event loop is single-threaded, but Node.js offloads blocking operations to a libuv thread pool. Here's how it works, what uses it, and how to tune it.

20 Sept 2026 · 2 min read