Skip to content

🎯 Reject JWTs with Out-of-Bounds Expiration (exp) Values to Prevent time.Time Overflow #1

Description

@heathivorjocelyn6

📝 Description

JWTs containing extremely large exp (Expiration Time) values currently trigger inconsistent behavior during claims validation. Depending on the platform and how the numeric value is parsed (e.g., as a float64 from JSON or cast to an integer), the parser may overflow, wrap around, or treat the token as effectively non-expiring.

To ensure consistent and secure validation, the parser must reject expiration timestamps (and other time-based claims like nbf and iat) that cannot be safely represented as a valid Go time.Time object or that exceed reasonable temporal boundaries.

🎯 Acceptance Criteria

  • The JWT parser must validate that the exp (Expiration Time), nbf (Not Before), and iat (Issued At) claims contain numeric values that can be safely converted to a Go time.Time without integer overflow or precision loss that alters validation logic.
  • Any token containing a time-based claim that exceeds the maximum representable time boundary (e.g., dates beyond the year 9999 or values causing overflow in time.Unix()) must be rejected immediately during validation.
  • The parser must return a specific, actionable validation error (e.g., ErrInvalidEpoch or ErrExpired / ErrMalformedClaims) when an out-of-bounds timestamp is encountered.
  • The validation must handle edge cases such as extremely large floating-point numbers (e.g., 1e20), maximum 64-bit integer values (9223372036854775807), and negative values if they represent invalid times.

🛠️ Technical Specifications & Context

In Go, JSON numbers are typically parsed as float64 or json.Number. When converting these values to Unix timestamps using time.Unix(), extremely large values can lead to unexpected times due to integer overflow or floating-point truncation.

Potential Areas of Modification:

  • claims.go / validation.go: Locate the validation logic where exp, nbf, and iat claims are extracted and verified.
  • Helper Functions: Implement a helper function to verify if a numeric claim (either float64 or json.Number) falls within a safe Unix timestamp range before passing it to time.Unix().
    • Safe Range Example: Unix time values should generally be between 0 (or a reasonable minimum like -62135596800 for Year 1) and 253402300799 (December 31, 9999 23:59:59 UTC) to prevent formatting and database compatibility issues, or at least bounded to prevent Go's internal time.Time representation from overflowing during comparisons (e.g., time.Now().After(exp)).
// Example check
const MaxUnixTime = 253402300799 // Year 9999

func isValidTimestamp(val float64) bool {
    return val >= 0 && val <= MaxUnixTime
}

🧪 Verification & Testing

To verify the fix, add unit tests in the test suite (e.g., claims_test.go or validation_test.go):

  1. Test Case: Maximum Integer Overflow

    • Attempt to parse/validate a token with exp set to 9223372036854775807.
    • Expected Result: Validation fails with an out-of-bounds or malformed claim error.
  2. Test Case: Large Floating Point

    • Attempt to parse/validate a token with exp set to 1e21.
    • Expected Result: Validation fails.
  3. Test Case: Valid Large Expiration

    • Attempt to parse/validate a token with a valid future date (e.g., year 2050 / 2524608000).
    • Expected Result: Validation succeeds (assuming the token is not expired relative to the current time).

Opire Bounty


This repo is using Opire - what does it mean? 👇
💵 Everyone can add rewards for this issue commenting /reward 100 (replace 100 with the amount).
🕵️‍♂️ If someone starts working on this issue to earn the rewards, they can comment /try to let everyone know!
🙌 And when they open the PR, they can comment /claim #1 either in the PR description or in a PR's comment.

🪙 Also, everyone can tip any user commenting /tip 20 @heathivorjocelyn6 (replace 20 with the amount, and @heathivorjocelyn6 with the user to tip).

📖 If you want to learn more, check out our documentation.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions