Skip to content

fix(siwe): reject unparseable expirationTime and notBefore - #4990

Merged
jxom merged 3 commits into
wevm:mainfrom
SashaMIT:fix/siwe-reject-invalid-expiration-dates
Aug 13, 2026
Merged

fix(siwe): reject unparseable expirationTime and notBefore#4990
jxom merged 3 commits into
wevm:mainfrom
SashaMIT:fix/siwe-reject-invalid-expiration-dates

Conversation

@SashaMIT

@SashaMIT SashaMIT commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

parseSiweMessage turns fields like Expiration Time: never into a truthy Invalid Date. In validateSiweMessage, the lifetime checks were:

if (message.expirationTime && time >= message.expirationTime) return false
if (message.notBefore && time < message.notBefore) return false

Comparisons against Invalid Date are always false, so both gates no-op and a signed SIWE message with garbage expiration / not-before still validates. This rejects unparseable dates when those fields are present (same class as thirdweb-dev/js#8875 and supabase/auth#2688).

Test plan

  • pnpm exec vitest run -c ./test/vitest.config.ts src/utils/siwe/validateSiweMessage.test.ts → 12/12
  • Cases for Expiration Time: never / garbage Not Before

Made with Cursor

Invalid Date values from parseSiweMessage (e.g. Expiration Time: never)
are truthy, so comparisons like `time >= expirationTime` are always
false and lifetime / nbf checks were skipped. Fail closed when either
field is present but not a real date (sibling of thirdweb-dev/js#8875 /
supabase/auth#2688).
@changeset-bot

changeset-bot Bot commented Aug 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 832afb1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
viem Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

@SashaMIT is attempting to deploy a commit to the Wevm Team on Vercel.

A member of the Team first needs to authorize it.

jxom commented Aug 10, 2026

Copy link
Copy Markdown
Member

Two remaining cases:

  • getTime() checks JavaScript date validity, not RFC 3339. Validate the raw SIWE timestamp before converting it to Date.
  • An invalid time makes both lifetime comparisons false. Reject it before checking expirationTime or notBefore.

See the ERC-4361 validation requirements.

Validate raw SIWE timestamps against the RFC 3339 profile before Date
coercion, and fail closed when the caller-supplied time is invalid so
lifetime comparisons cannot be skipped.
@SashaMIT

Copy link
Copy Markdown
Contributor Author

Thanks @jxom. Follow-up covers both cases:

  1. Raw SIWE timestamps are checked against the EIP-4361 / RFC 3339 profile before Date coercion in parseSiweMessage.
  2. Invalid caller time is rejected before expirationTime / notBefore comparisons.

Added a changeset. SIWE unit tests green locally (25/25).

@jxom
jxom merged commit cd1d2d5 into wevm:main Aug 13, 2026
2 of 3 checks passed
@github-actions github-actions Bot mentioned this pull request Aug 13, 2026
@SashaMIT

Copy link
Copy Markdown
Contributor Author

Thanks for the merge @jxom. Glad the RFC 3339 and invalid-time follow-up landed with the original fail-closed checks.

jxom added a commit that referenced this pull request Aug 14, 2026
* feat: add block header watcher (#4999)

* fix: complete block header watcher integration (#5001)

* chore: version package (#5000)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix(tempo): bind encrypted deposits to sender (#5002)

* fix(tempo): bind encrypted deposits to sender

Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com>

* ci: test sender-bound zone deposits

* ci: align Tempo and Zone fixtures

* test(tempo): routed T10 fixtures through encrypted deposits

* chore: logged local Zone provisioning stall

* chore: ignored unpatched extract-zip advisory

* fix(tempo): defaulted encrypted deposit sender

* ci: skipped Wagmi verification

* chore: remove friction log

---------

Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com>
Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com>
Co-authored-by: Steven Truong <struong@users.noreply.github.com>
Co-authored-by: jxom <7336481+jxom@users.noreply.github.com>

* chore: version package (#5003)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix(siwe): reject unparseable expirationTime and notBefore (#4990)

* fix(siwe): reject unparseable expirationTime and notBefore

Invalid Date values from parseSiweMessage (e.g. Expiration Time: never)
are truthy, so comparisons like `time >= expirationTime` are always
false and lifetime / nbf checks were skipped. Fail closed when either
field is present but not a real date (sibling of thirdweb-dev/js#8875 /
supabase/auth#2688).

* fix(siwe): require EIP-4361 date-time strings and reject invalid time

Validate raw SIWE timestamps against the RFC 3339 profile before Date
coercion, and fail closed when the caller-supplied time is invalid so
lifetime comparisons cannot be skipped.

* fix(siwe): inline date validation

---------

Co-authored-by: jxom <7336481+jxom@users.noreply.github.com>

* fix: asset discovery in `simulateCalls` (#4997)

* fix(simulateCalls): discover assets from simulated logs

* refactor(simulateCalls): align asset discovery with repo conventions

* fix(simulateCalls): pin both asset-tracing passes to one base block

* test(simulateCalls): skip asset tracing on the pinned Anvil

* chore: update accessListHints comment

* fix(simulateCalls): preserve block tags and request errors

* fix(simulateCalls): harden asset trace discovery

* test: use reth for mainnet forks

* test(simulateCalls): run asset tracing against reth

* fix(simulateCalls): align asset trace simulations

* fix(simulateCalls): stabilize asset tracing

* chore: add static call source

* fix(simulateCalls): simplify asset tracing

* fix(simulateCalls): isolate asset balance probes

* fix(simulateCalls): align asset probe callers

* fix(simulateCalls): preserve pending block tag

* fix(simulateCalls): normalize transfer topics

* refactor(simulateCalls): remove redundant asset deduplication

* test(simulateCalls): cover asset tracing edge cases

* docs(simulateCalls): describe pending asset tracing

---------

Co-authored-by: jxom <7336481+jxom@users.noreply.github.com>

* fix: update nanoid security override

* fix: increase package size limits

* ci: remove docs deployment

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: struong <steven@tempo.xyz>
Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com>
Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com>
Co-authored-by: Steven Truong <struong@users.noreply.github.com>
Co-authored-by: Sash <sash@ela.city>
Co-authored-by: Ghadi <92851745+Ghadi8@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants