require-max-age
**Severity:** � Medium
Require maxAge option in verify operations to enforce token freshness
Severity: 🟡 Medium
CWE: CWE-294
Rule Details
This rule mandates maxAge in verify operations. Without it, tokens can be replayed years after issuance.
Examples
❌ Incorrect
jwt.verify(token, secret);
jwt.verify(token, secret, { algorithms: ['RS256'] });✅ Correct
jwt.verify(token, secret, { maxAge: '1h' });
jwt.verify(token, secret, {
algorithms: ['RS256'],
maxAge: '24h',
});Known False Negatives
The following patterns are not detected due to static analysis limitations:
Options from Variable
Why: Variable contents are not analyzed.
// ❌ NOT DETECTED - Options from variable
const opts = { algorithms: ['RS256'] }; // Missing maxAge
jwt.verify(token, secret, opts);Mitigation: Use inline options. Create TypeScript types requiring maxAge.
Spread Options
Why: Spread properties hide the actual options at lint time.
// ❌ NOT DETECTED - maxAge may be missing in base
const baseOpts = getVerifyOptions(); // No maxAge
jwt.verify(token, secret, { ...baseOpts });Mitigation: Always specify maxAge explicitly. Avoid spreading untrusted options.
Runtime MaxAge Configuration
Why: MaxAge from runtime config is not visible.
// ❌ NOT DETECTED - MaxAge from config
jwt.verify(token, secret, { maxAge: config.tokenMaxAge }); // Might be undefinedMitigation: Validate config at startup. Use required fields in TypeScript config types.
Excessive MaxAge Values
Why: Very large maxAge values (e.g., '100y') pass but are effectively non-enforcing.
// ❌ NOT DETECTED - Effectively no max age enforcement
jwt.verify(token, secret, { maxAge: '100y' });Mitigation: Add option for maximum allowed maxAge value. Validate at runtime.
Wrapper Function
Why: Options passed through wrappers are not traced.
// ❌ NOT DETECTED - Wrapper hides options
function verifyToken(token: string, opts = {}) {
return jwt.verify(token, secret, opts); // opts may lack maxAge
}Mitigation: Apply this rule to all modules including utilities.