require-issued-at
**Severity:** � Medium
Require iat (issued at) claim for token freshness validation
Severity: 🟡 Medium
CWE: CWE-294
Rule Details
This rule ensures tokens have the iat claim for freshness validation. Most libraries add iat automatically unless explicitly disabled.
Examples
❌ Incorrect
// Explicitly disables iat
jwt.sign(payload, secret, { noTimestamp: true });✅ Correct
// Default - iat is added automatically
jwt.sign(payload, secret);
// Explicit iat in payload
jwt.sign({ sub: 'user', iat: Math.floor(Date.now() / 1000) }, secret);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 - noTimestamp in variable
const opts = { noTimestamp: true };
jwt.sign(payload, secret, opts);Mitigation: Use inline options. Use TypeScript types forbidding noTimestamp: true.
Payload Without iat When noTimestamp Is Not Used
Why: The rule primarily checks for noTimestamp: true, not payload contents.
// ⚠️ EDGE CASE - Most libraries auto-add iat, so this is usually safe
jwt.sign({ sub: 'user' }, secret); // iat added automaticallyMitigation: Rely on library defaults. Use require-max-age for verification-side checks.
Library Without Auto-iat
Why: Some JWT libraries don't auto-add iat, which the rule assumes.
// ❌ NOT DETECTED - Library doesn't auto-add iat
import { sign } from 'minimal-jwt-lib';
sign({ sub: 'user' }, secret); // No iat and none added by libraryMitigation: Verify library behavior. Add explicit iat in payload.
Spread Options
Why: Spread properties hide the actual options at lint time.
// ❌ NOT DETECTED - noTimestamp in spread
const baseOpts = { noTimestamp: true };
jwt.sign(payload, secret, { ...baseOpts, expiresIn: '1h' });Mitigation: Avoid spreading sign options. Specify options explicitly.