Interlace ESLint
ESLint Interlace

no-weak-secret

**Severity:** � High

Require strong secrets (256+ bits) for HMAC-based JWT signing

Severity: 🟠 High
CWE: CWE-326

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

⚠️ CWE-326 OWASP:A04 CVSS:5.9 | Inadequate Encryption Strength detected | MEDIUM
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A04_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-326 OWASP:A04 CVSS:5.9
Issue DescriptionSpecific vulnerabilityInadequate Encryption Strength detected
Severity & ComplianceImpact assessmentMEDIUM
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Rule Details

This rule detects weak secrets used for HMAC-based JWT signing. Weak secrets can be brute-forced offline, allowing attackers to forge tokens.

Examples

❌ Incorrect

// Known weak patterns
jwt.sign(payload, 'secret');
jwt.sign(payload, 'password');
jwt.sign(payload, 'changeme');

// Short secrets (<32 characters)
jwt.sign(payload, 'shortkey');

✅ Correct

// Environment variable
jwt.sign(payload, process.env.JWT_SECRET);

// Long secret (32+ characters)
jwt.sign(payload, 'ThisIsAVeryStrongSecretThatIs32Ch+');

// Generated secret
jwt.sign(payload, crypto.randomBytes(32).toString('hex'));

Options

{
  "jwt/no-weak-secret": ["error", {
    "minSecretLength": 32
  }]
}
OptionTypeDefaultDescription
minSecretLengthinteger32Minimum secret length (chars)

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Variable References

Why: Only literal string secrets are analyzed for length/weakness.

// ❌ NOT DETECTED - Secret from variable
const weakSecret = 'abc';
jwt.sign(payload, weakSecret); // Variable not analyzed

Mitigation: Use environment variables. Apply TypeScript branded types for validated secrets.

Concatenated Secrets

Why: String operations are not evaluated statically.

// ❌ NOT DETECTED - Concatenated weak parts
const part1 = 'short';
const part2 = 'key';
jwt.sign(payload, part1 + part2); // Still weak, but not detected

Mitigation: Use single, long secret strings. Avoid dynamic secret construction.

Encoded Weak Secrets

Why: Base64/hex encoding can hide a weak underlying secret.

// ❌ NOT DETECTED - Encoded but short underlying value
const encoded = Buffer.from('weak').toString('base64'); // 'd2Vhaw=='
jwt.sign(payload, encoded); // String is long enough but entropy is low

Mitigation: Validate secret entropy at runtime. Use cryptographically random secrets.

Environment Variable Values

Why: The rule trusts environment variables but cannot verify their actual values.

// ❌ NOT DETECTED - Weak secret in env var
// .env: JWT_SECRET=password
jwt.sign(payload, process.env.JWT_SECRET); // Trusts the env var

Mitigation: Use secret rotation policies. Validate secret strength at application startup.

Secrets from Configuration Files

Why: Values loaded from config files are treated as safe.

// ❌ NOT DETECTED - Weak secret in config
import { JWT_SECRET } from './config'; // Config contains 'weak123'
jwt.sign(payload, JWT_SECRET);

Mitigation: Apply secret validation at config load time. Use environment variables for secrets.

Further Reading

On this page