ESLint InterlaceESLint Interlace
Plugin: node-securityRules

no-insecure-key-derivation

ESLint rule documentation for no-insecure-key-derivation

📡 Live from GitHub — This documentation is fetched directly from no-insecure-key-derivation.md and cached for 6 hours.

Keywords: PBKDF2, key derivation, iterations, password hashing, CWE-916, security, ESLint rule, scrypt, Argon2 CWE: CWE-916
OWASP: A02:2021-Cryptographic Failures

Disallow PBKDF2 with insufficient iterations (< 100,000)

Detects PBKDF2 usage with insufficient iterations. OWASP 2023 recommends minimum 600,000 iterations for PBKDF2-SHA256. This rule is part of eslint-plugin-node-security and provides LLM-optimized error messages with fix suggestions.

🚨 Security rule | 💡 Provides suggestions | ⚠️ Set to error in recommended

Quick Summary

AspectDetails
CWE ReferenceCWE-916 (Weak Hashing)
SeverityHigh (security vulnerability)
Auto-Fix💡 Suggests fixes (increase iterations, use scrypt/Argon2)
CategorySecurity
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForNode.js applications hashing passwords or deriving keys

Vulnerability and Risk

Vulnerability: PBKDF2 with low iteration counts allows attackers to perform brute-force attacks efficiently. Each iteration adds computational cost, so low counts make password cracking feasible with modern GPUs.

Risk: With only 10,000 iterations, an attacker with commodity hardware can test billions of password guesses. OWASP 2023 recommends 600,000+ iterations for PBKDF2-SHA256 to provide adequate protection.

Rule Details

This rule detects crypto.pbkdf2() and crypto.pbkdf2Sync() calls where the iteration count is below the configurable minimum (default: 100,000).

Why This Matters

RiskImpactSolution
💨 Fast CrackingLow iterations = fast brute forceUse 100,000+ iterations minimum
🎮 GPU AttacksGPUs can test billions of hashes/secondUse scrypt or Argon2 (memory-hard)
🔒 ComplianceFails OWASP, NIST password requirementsFollow OWASP 2023 guidelines

Configuration

OptionTypeDefaultDescription
minIterationsnumber100000Minimum required PBKDF2 iterations
{
  rules: {
    'node-security/no-insecure-key-derivation': ['error', {
      minIterations: 600000 // OWASP 2023 recommendation
    }]
  }
}

Examples

❌ Incorrect

import crypto from 'crypto';

// Only 10,000 iterations - too weak
crypto.pbkdf2(password, salt, 10000, 32, 'sha256', callback);

// 1,000 iterations - critically weak
const key = crypto.pbkdf2Sync(password, salt, 1000, 32, 'sha512');

// 50,000 iterations - still below minimum
crypto.pbkdf2(password, salt, 50000, 32, 'sha256', callback);

✅ Correct

import crypto from 'crypto';

// 100,000+ iterations (minimum)
crypto.pbkdf2(password, salt, 100000, 32, 'sha256', callback);

// 600,000 iterations (OWASP 2023 recommendation)
const key = crypto.pbkdf2Sync(password, salt, 600000, 32, 'sha256');

// Better: Use scrypt (memory-hard)
const scryptKey = crypto.scryptSync(password, salt, 32, {
  N: 16384, // CPU/memory cost
  r: 8, // Block size
  p: 1, // Parallelization
});

// Best: Use Argon2id (winner of Password Hashing Competition)
import argon2 from 'argon2';
const hash = await argon2.hash(password, { type: argon2.argon2id });

Security Impact

VulnerabilityCWEOWASPCVSSImpact
Weak Password Hash916A02:20217.5 HighPassword cracking
Insufficient Effort916A07:20215.3 MediumBrute force feasibility

OWASP 2023 Recommendations

AlgorithmMinimum Work Factor
PBKDF2-SHA256600,000 iterations
PBKDF2-SHA512210,000 iterations
bcryptCost factor 10+
scryptN=2^17 (131072), r=8, p=1
Argon2idm=19456, t=2, p=1

Migration Guide

Phase 1: Discovery

{
  rules: {
    'node-security/no-insecure-key-derivation': 'warn'
  }
}

Phase 2: Increase Iterations

// Increase PBKDF2 iterations
crypto.pbkdf2(password, salt, 10000, 32, 'sha256', cb); // ❌ Before
crypto.pbkdf2(password, salt, 600000, 32, 'sha256', cb); // ✅ After

Phase 3: Consider Alternatives

// Migrate to scrypt for memory-hard protection
crypto.scrypt(password, salt, 32, (err, key) => {});

// Or use Argon2id (recommended for new applications)
const hash = await argon2.hash(password, { type: argon2.argon2id });

Known False Negatives

Variable Iterations

Why: Dynamic values cannot be analyzed statically.

// ❌ NOT DETECTED
const iterations = config.iterations; // Runtime value
crypto.pbkdf2(password, salt, iterations, 32, 'sha256', cb);

Mitigation: Validate configuration at startup.

Further Reading

On this page

No Headings