Key validity window
Optional nbf and exp on a key must be coherent: in seconds, not already expired, already valid, and not an absurdly long window.
What this check verifies
A key may carry optional nbf (not before) and exp (expires) members, each a numeric timestamp in seconds since the Unix epoch. These bound the period a key is meant to be used. They are optional; a key with neither is fine.
When they are present, this check confirms they are coherent:
- If
expis in the past, the key is already expired. This fails. - If
nbforexplooks like milliseconds (a value above 100 billion, which in seconds would be after the year 5000), the check warns. Read as seconds, annbfin milliseconds makes the key not yet valid for thousands of years, and anexpin milliseconds makes it never expire. - If
nbfis more than five minutes in the future, the key is not valid yet, and the check warns. - If both
nbfandexpare present and the window between them is longer than about 400 days, the check warns that the validity window is unusually long. - Otherwise it passes.
{ "kty": "OKP", "crv": "Ed25519", "x": "...", "kid": "...",
"nbf": 1735689600, "exp": 1767225600 }
Why it matters
An already-expired key should not be signing anything. Publishing one in the active directory is a contradiction: the directory says “use this key” while the key says “I am no longer valid.” A verifier that honors exp will reject signatures made with it, so leaving an expired key in the directory either breaks verification or signals that rotation did not finish. The checker fails this case.
A key that is not valid yet, or whose nbf is in milliseconds, is rejected by every verifier that honors nbf until that date, so signatures made with it fail there. An exp in milliseconds means the key never expires, which defeats the point of setting it.
A very long validity window is the opposite problem. Short-lived keys limit the exposure if a key is compromised, because the window in which a leaked key is accepted is bounded. A window of years undercuts that benefit. The checker warns rather than fails here, because a long window is a policy weakness, not a broken directory.
The expired case is a real failure; the millisecond, not-yet-valid and long-window cases are advisory warnings. Neither makes the directory structurally invalid, but an expired key is a genuine fault worth fixing before it breaks verification.
How to fix it
- Remove or rotate any key whose
expis in the past. A new key should replace the expired one in the directory. - Write
nbfandexpin seconds since the Unix epoch. A JavaScriptDate.now()value is in milliseconds; divide it by 1000. - If you set a validity window, keep it bounded. A window under roughly a year keeps the key fresh and limits exposure if it leaks; the checker warns past about 400 days.
- If you do not need to bound a key’s lifetime, you may omit
nbfandexpentirely and rotate keys operationally instead.
The usual cause of the failure is a rotation that added a new key but never removed the expired one. The usual cause of the millisecond warning is a JavaScript Date.now() value written without dividing by 1000; the usual cause of the long-window warning is setting exp years out by default. After the fix, no published key should be expired, and any window you set should be reasonably short.
References
- RFC 7519 defines
nbfandexpas times in seconds since the Unix epoch (as JWT claims). RFC 7517, the JSON Web Key format, does not define them; JWK sets carry them as additional members. - The Web Bot Auth protocol draft (draft-ietf-webbotauth-httpsig-protocol-00) shows
nbfandexpin its directory example (section 5.5.1) and does not require them; section 5.5.2 describes key rotation. - How grading works explains how an expired key fails while the other cases only warn.
How the checker scores this
- Tier
- JWKS directory
- Role
- Advisory. Failing this never caps the grade or changes the verdict.
- Point deduction
- A failure deducts 25 points; a warning deducts 6.