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
| Component | Purpose | Example |
|---|---|---|
| Risk Standards | Security benchmarks | CWE-326 OWASP:A04 CVSS:5.9 |
| Issue Description | Specific vulnerability | Inadequate Encryption Strength detected |
| Severity & Compliance | Impact assessment | MEDIUM |
| Fix Instruction | Actionable remediation | Follow the remediation steps below |
| Technical Truth | Official reference | OWASP 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
}]
}| Option | Type | Default | Description |
|---|---|---|---|
minSecretLength | integer | 32 | Minimum 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 analyzedMitigation: 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 detectedMitigation: 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 lowMitigation: 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 varMitigation: 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.