Reproducing a one-time challenge replay race with 200 contenders
An action-bound challenge guard was tested under concurrent scheduled consumption, including binding mismatch, expiry and replay behavior. Here's what the result proves and what it doesn't.
When a mobile client presents a valid one-time challenge, the critical question is not whether a signature looks right. It is whether the backend can prevent two acceptance decisions for the same token.
This is a reproducible synthetic engineering experiment, not a claim about a vulnerability in someone else's system or a production authentication deployment. The test source is public at ZombieMutex Replay Guard.
Hypothesis and test boundary
Hypothesis: A synchronous check-and-consume operation in a single Node.js event loop should allow precisely one successful claim, even when multiple Promise callbacks try to consume the same token.
This is intentionally a limited test of a local in-memory model. A separate process, geographically distributed service, crashed worker, and externally shared database would have different concurrency and persistence properties.
Reproduce the experiment
The public repository has no npm dependencies. On Node.js 24.21 (macOS Apple Silicon was used for this local validation), clone the repo and run:
One test creates a one-time token for principal “a” and action “sign”, schedules 200 Promise-based consume calls for that same token, and counts successful results.
Observed results
| Test case | Observed local outcome |
|---|---|
| Same token consumed by 200 scheduled callbacks | Exactly 1 accepted; 199 rejected |
| Reuse after successful consume | Rejected as already used |
| A different principal or action uses that token | Context mismatch; rejected |
| Challenge used after configured expiry | Rejected |
| Expired record swept | 1 expired record removed in test |
All five repository tests passed in the local execution used to publish this report. These are test assertions, not throughput benchmarks or live network measurements.
Why this result is insufficient for production
The map-based consume is synchronous and local to one JavaScript process. It does not address the classic check-then-set race when two independent workers consult a shared datastore, where both can observe an unused token.
A deployable system needs a durable authoritative challenge store and an atomic claim operation. That typically means a transactional unique constraint or compare-and-swap primitive across every worker and region allowed to accept the proof. The token is a replay guard input; it is not App Attest verification, account authentication, or per-object authorization.
The test harness also returns detailed rejection reasons for investigation. An externally exposed endpoint may need uniform errors, request rate limits and privacy-safe event telemetry to avoid creating a new oracle.
What to test next
The next experiment should use an actual shared database with concurrent independent processes and crash injection between validation and commit. Verify a single winner across process boundaries, recovery after abrupt termination, retention, one-time-use expiration, and the behavior when the datastore is unavailable.
Try the linked browser replay simulation and read device integrity versus authorization for the platform-specific trust distinction.
Provenance: A new AI-assisted ZombieMutex reference project and its actual local automated test results. No client code, production incident or independent security audit is represented.
Continue exploring
Related technical notes with overlapping topics.