Skip to content

hardening(security): require exp claim when verifying access and reset JWTs - #2514

Closed
failsafesecurity wants to merge 2 commits into
fastapi:masterfrom
failsafesecurity:hardening/jwt-claim-validation
Closed

failsafesecurity wants to merge 2 commits into
fastapi:masterfrom
failsafesecurity:hardening/jwt-claim-validation

Conversation

@failsafesecurity

Copy link
Copy Markdown

Summary

Companion hardening PR to the fail-closed SECRET_KEY fix (#2513). Independently of the signing key, a JWT that carries no exp claim must never authenticate.

Related finding: Shipped default SECRET_KEY with fail-open validation permits forgery of any JWT (CRITICAL · CVSS 4.0 9.3 · CWE-321)
Scan ID: cmv17pczu00womo01ei5nap4f

What this changes

  • backend/app/api/deps.py::get_current_user now calls jwt.decode(..., options={"require": ["exp"]}), so an access token without an expiry is rejected.
  • backend/app/utils.py::verify_password_reset_token requires exp as well, so a reset token without a lifetime bound can never be replayed.
  • New backend/tests/api/routes/test_jwt_claims.py asserts:
    • a correctly signed token without exp is rejected,
    • the same token with exp is accepted,
    • the password-reset verifier returns None without exp and the subject with it,
    • a token signed with the wrong key is rejected.

Why

Requiring exp is defense-in-depth for the same trust boundary the main fix hardens: tokens are the only thing standing between an unauthenticated caller and superuser access, so verification should never accept a token with an unbounded lifetime.

Notes

Pure verification tightening; valid existing tokens (which always include exp) are unaffected.

failsafesecurity and others added 2 commits October 9, 2026 17:15
…t JWTs

Companion hardening for the shipped-default-secret finding. Even with a
fail-closed signing key, a correctly signed token without an exp claim should
never authenticate.

- get_current_user rejects access tokens lacking exp (jwt.decode require=[exp]).
- verify_password_reset_token requires exp as well.
- Adds backend/tests/api/routes/test_jwt_claims.py covering: no-exp token is
  rejected, valid exp token accepted, reset token requires exp, and a token
  signed with the wrong key is rejected.
@github-actions

Copy link
Copy Markdown
Contributor

This was marked as potentially AI generated and will be closed now. If this is an error, please provide additional details, make sure to read the docs about contributing and AI.

@github-actions github-actions Bot closed this Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants