CVE-2026-102414 Overview
CVE-2026-102414 affects the pbkdf2 npm package through version 3.1.6. The library's JavaScript fallback in lib/sync.js re-hashes long passwords on every PBKDF2 iteration instead of pre-hashing once. When a password exceeds the HMAC block size (64 bytes, or 128 bytes for SHA-384 and SHA-512), the total work becomes O(iterations × password length). An attacker submitting a long password can stall the Node.js event loop and cause a denial of service. The fallback path is reached on Node.js before 0.12, on Bun 1.0.0 through 1.1.34 and 1.2.6+, on Deno 2.9.0+, and whenever lib/sync.js is imported directly. This weakness is tracked as [CWE-400].
Critical Impact
Attackers submitting oversized passwords can block the event loop of affected runtimes, degrading availability of authentication endpoints that rely on the vulnerable pbkdf2 fallback.
Affected Products
- pbkdf2 npm package versions up to and including 3.1.6 (JavaScript fallback in lib/sync.js)
- Applications running on Bun 1.0.0 through 1.1.34, and Bun 1.2.6 and later
- Applications running on Deno 2.9.0 and later, and Node.js versions before 0.12
Discovery Timeline
- 2026-09-29 - CVE-2026-102414 published to the National Vulnerability Database (NVD)
- 2026-09-30 - Last updated in NVD database
Technical Details for CVE-2026-102414
Vulnerability Analysis
PBKDF2 (Password-Based Key Derivation Function 2) derives a key by repeatedly applying HMAC over a password and salt. Standard implementations pre-hash any password longer than the HMAC block size a single time, then reuse the digest across iterations. The pbkdf2 JavaScript fallback in lib/sync.js does not perform this pre-hash. Instead, it passes the raw long password to createHmac as the key on each of the configured iterations. HMAC internally hashes any oversized key on every call, so the per-iteration cost scales linearly with password length.
The result is an algorithmic complexity issue where a request containing a multi-megabyte password consumes CPU for hundreds of thousands of iterations. Because Node.js and compatible runtimes execute synchronous work on a single event loop thread, a single expensive pbkdf2Sync call blocks all other request processing until it completes.
Root Cause
The root cause is a missing pre-hash step for HMAC keys larger than the digest block size inside lib/sync.js. The library relies on the runtime's native pbkdf2Sync, but its feature check fails on Bun, Deno 2.9.0+, and Node.js before 0.12, silently downgrading callers to the vulnerable pure-JavaScript implementation.
Attack Vector
The attack requires an application to accept an unbounded password field and forward it to pbkdf2 or pbkdf2Sync on an affected runtime. A remote attacker sends a request containing a very long password to any endpoint that derives a key or verifies a stored hash. No authentication or user interaction is required. Applications that enforce a reasonable maximum password length are not meaningfully affected.
// Security patch in lib/sync.js - hash long passwords once, not on every iteration
'ripemd-160': 'ripemd160'
};
+var createHash = require('create-hash');
var createHmac = require('create-hmac');
var Buffer = require('safe-buffer').Buffer;
// Source: https://github.com/browserify/pbkdf2/commit/493d8d8
The patch introduces create-hash so the fallback can pre-hash oversized keys once before entering the iteration loop, restoring O(iterations) complexity independent of password length.
Detection Methods for CVE-2026-102414
Indicators of Compromise
- Authentication or key-derivation endpoints returning elevated latency or timeouts under low request volume
- HTTP requests containing password or passphrase fields with body sizes far exceeding normal user input (for example, tens of kilobytes or more)
- Sustained single-core CPU saturation on Node.js, Bun, or Deno workers correlated with individual inbound requests
Detection Strategies
- Inventory Node.js, Bun, and Deno services for the pbkdf2 package at versions ≤ 3.1.6 using npm ls pbkdf2 or lockfile scanning across CI pipelines
- Identify direct imports of pbkdf2/lib/sync.js in application code and dependency trees, since these bypass the native runtime check
- Add application-level metrics that record password field length at authentication and key-derivation call sites, and alert on outliers
Monitoring Recommendations
- Track event loop lag on Node.js and Bun workers, alerting when lag exceeds normal baselines during authentication traffic
- Log and rate-limit requests to endpoints performing PBKDF2 operations, particularly login, registration, and token endpoints
- Correlate reverse-proxy request body sizes with backend CPU spikes to surface algorithmic complexity abuse patterns
How to Mitigate CVE-2026-102414
Immediate Actions Required
- Upgrade pbkdf2 to a version above 3.1.6 that includes commit 493d8d8 across all Node.js, Bun, and Deno services
- Enforce a maximum password length (for example, 128 or 256 bytes) at the application boundary before invoking any key derivation function
- Audit code for direct imports of pbkdf2/lib/sync.js and route callers through the package entry point so runtime native implementations are used when available
Patch Information
The fix is delivered in the pbkdf2 commit 493d8d8, which adds a create-hash pre-hash step for oversized HMAC keys in lib/sync.js. Additional context is available in the GitHub Security Advisory GHSA-477h-4r7f-fvrx and the upstream issue discussion.
Workarounds
- Enforce a strict input length cap on password and passphrase fields at the web tier or API gateway before any PBKDF2 call
- On Node.js 0.12 or later, ensure the runtime's native pbkdf2Sync is used and avoid pinning to legacy runtimes that fail the library's feature check
- Where feasible, migrate to a maintained key derivation library or the runtime's built-in crypto.pbkdf2 and remove direct references to pbkdf2/lib/sync.js
# Configuration example: upgrade the vulnerable package and verify resolution
npm install pbkdf2@latest
npm ls pbkdf2
# Optional: express body size limit to constrain oversized password submissions
# app.use(express.json({ limit: '16kb' }));
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.