← All casesConfidential · Anonymized
Case
#020
Web3 · Wallet · Severity: High
Wallet Session Fixation
The wallet-connect handshake accepted a session token issued before the connect flow completed. A narrow timing window allowed a session token to be substituted, resulting in cross-origin session fixation across dApps sharing the wallet.
Industry
Web3 · Wallet
Scope
Wallet · Session · Application
Timeline
R·Q4 → V·Q4 → R·Q1
Closed
Q1
01
Impact
Session hijack
Signer authorization bound to attacker-controlled session
Cross-dApp
Token confusion across dApps sharing the wallet
Attack window
≤ 800 ms during the connect handshake
Impact vectors
- ›Session hijack under connect flow
- ›Cross-dApp token confusion
02
Reproduction
Steps below reproduce the finding against a staging replica. Where the reproduction affected a shared component, coordination was arranged before execution.
- 01Pre-issue a session token from the target dApp origin.
- 02Trigger a wallet connect flow from a controlled origin.
- 03Substitute the session token during the handshake acknowledgement.
- 04Confirm subsequent signer authorizations bind to the substituted session.
03
Vulnerability
async function onConnectAck(msg: ConnectAck) {
const session = await store.get(msg.sessionId);
if (!session) return reject('no session');
session.status = 'connected';
await store.put(session);
}04
Mitigation
Client-side mitigation shipped and validated during the engagement. Reference patch below.
async function onConnectAck(msg: ConnectAck, origin: string) {
const session = await store.get(msg.sessionId);
if (!session || session.origin !== origin) return reject('origin mismatch');
if (!verifyChallenge(msg.challenge, session.nonce)) return reject('challenge failed');
session.status = 'connected';
session.nonce = rotateNonce(); // one-shot per handshake
await store.put(session);
}05
Retest & Verify
- ✓Handshake rejects any token whose recorded origin differs from the ACK origin.
- ✓Challenge nonce is single-use and rotates on completion.
- ✓Cross-dApp reproduction attempts rejected in 100/100 trials.
06
Deliverables
- ▊Technical Report
- ▊Session model review
- ▊Origin-bound challenge implementation
- ▊Retesting report
07
Sign-off
Handled by
Epulyx
Reviewed by
Nolan
Closed
Case closed after fixation path verified closed.