feat: add maxReceiptAgeSeconds to limit hash-credential historical replay#10
Merged
Merged
Conversation
markwu35
approved these changes
Apr 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Addresses the security review's finding on
verifyHash: the credential payload binds nothing to the specific challenge, so any historical Transfer to the recipient matching the requested token + amount can be claimed as proof of payment, once each.This adds an opt-in server config option
maxReceiptAgeSeconds. When set,verifyHashfetches the receipt's block and rejects any receipt whose timestamp is older than N seconds at verification time. When unset, behavior is unchanged from today (no age limit).Why opt-in (no default)
A default would silently change verification semantics for every existing operator on upgrade. Operators on slow chains (or with long retry budgets) might see legitimate payments rejected; operators with sub-second confirmation could already be tighter. Without a sensible universal default, opt-in is the right shape — operators consciously pick a value that matches their chain + UX.
What it does and doesn't fix
Files changed
Test plan
Note
Medium Risk
Adds an opt-in age check to
hashreceipt verification, which can reject previously-accepted payments if misconfigured and impacts a security-sensitive payment-verification path.Overview
Adds an opt-in server configuration
maxReceiptAgeSecondsthat, when set, makesverifyHashfetch the receipt block timestamp and rejecthashcredentials older than the configured window.Threads the new option through
evm.chargeserver parameters, updates README configuration/docs with a caution abouthash’s weak binding, and expandshashverifier tests to cover accept/reject behavior and reservation release on age-based rejection.Reviewed by Cursor Bugbot for commit 1839ccb. Bugbot is set up for automated code reviews on this repo. Configure here.