fix(verify): require expires and apply clock-skew tolerance to it - #3
Merged
Merged
Conversation
…uest verify_request had two gaps in the freshness gate: 1. max_skew was applied to the created (future) check but not the expires check, so a verifier whose clock runs slightly fast would reject a signature only a few seconds past expiry (RFC 9421 3.2.1 allows skew tolerance on both). 2. A signature that omitted expires entirely passed the expiry gate and verified forever, making it replayable indefinitely. Web Bot Auth signatures are short-lived and must carry an expiry. Require expires to be present, and tolerate max_skew past it. Add tests for skew-within-tolerance, skew-beyond-tolerance, and missing-expires.
AmirF194
approved these changes
Jul 10, 2026
AmirF194
left a comment
Owner
There was a problem hiding this comment.
Both fixes are correct and well-tested. The missing-expires gate closes a real replay hole, and the now > expires + max_skew change makes the skew tolerance symmetric with the created check (RFC 9421 §3.2.1). Verified the suite passes locally across the rfc9421 tests. Thanks!
Merged
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.
Problem
The freshness gate in
verify_requesthas two gaps:1. Clock-skew tolerance is applied asymmetrically.
max_skewis applied to thecreated(future) check but not theexpirescheck:So a verifier whose clock runs a little fast rejects a signature that is only a few seconds past
expires, even though it is still valid on the signer's clock. RFC 9421 §3.2.1 says the skew tolerance should apply to bothcreatedandexpires.2. A signature with no
expiresverifies forever. The check is skipped entirely whenexpiresis absent, then a passing "signature not expired" mark is recorded. A Web Bot Auth signature that omitsexpirestherefore passes the expiry gate and — if the key resolves and the crypto checks out — is accepted indefinitely, i.e. replayable. Web Bot Auth signatures are short-lived and are required to carry an expiry.Reproduction (before this change)
Fix
In
verify_request:expires— reject when it is absent ("signature has no expires (web-bot-auth requires one)").max_skewpastexpires(now > expires + max_skew), mirroring the existing allowance oncreated.verify_directoryis intentionally left unchanged: directory signatures are long-lived (365d) and pre-signed offline, so request-style clock skew doesn't apply.Tests
Added to tests/test_rfc9421.py:
test_expiry_tolerates_clock_skew_within_max_skew— expired 100s ago is accepted withmax_skew=300.test_expiry_beyond_skew_still_fails— expired 400s ago is still rejected.test_signature_without_expires_is_rejected— a hand-crafted, cryptographically valid signature that omitsexpiresis rejected.The existing
test_verify_fails_when_expired(expired ~9940s, far beyond skew) still passes. Full suite: 45 passed (42 + 3 new).