Negative balance achieved through TOCTOU attack.
| ID | Time | Amount | Status | Account 1 After | Account 2 After |
|---|---|---|---|---|---|
| {{ op.id }} | {{ op.time.toLocaleTimeString() }} | ${{ op.amount.toFixed(2) }} | {{ op.status }} | ${{ op.account1After.toFixed(2) }} | ${{ op.account2After.toFixed(2) }} |
By performing {{ concurrentRequests }} concurrent transfers of ${{ transferAmount }} each while intentionally delaying operations by {{ operationDelay }}ms, we were able to:
This demo shows a classic Time-of-Check to Time-of-Use (TOCTOU) race condition in banking systems. The vulnerability occurs when funds are transferred between accounts without proper locking.
// UNSAFE - Vulnerable to TOCTOU
async function transferVulnerable(amount) {
// 1. Check balance (Time-of-Check)
if (account1.balance >= amount) {
// 2. WINDOW OF VULNERABILITY - Other threads can pass the check
// 3. Simulate processing delay
await delay(operationDelay);
// 4. Transfer funds (Time-of-Use)
account1.balance -= amount;
account2.balance += amount;
return true;
}
return false;
}
// SAFE - Uses locking to prevent race conditions
async function transferProtected(amount) {
const release = await account1.lock.acquire();
try {
if (account1.balance >= amount) {
// No window of vulnerability
account1.balance -= amount;
account2.balance += amount;
return true;
}
return false;
} finally {
release();
}
}