TL;DR
Race conditions occur when the outcome depends on timing between concurrent operations. In security, TOCTOU (time-of-check to time-of-use) bugs let attackers change state between when you check something and when you act on it. Use atomic operations, database transactions, and proper locking to prevent them.
Common Race Condition Examples
Double-Spend in Wallet Applications
app.post('/transfer', async (req, res) => {
const { amount, toUser } = req.body;
// Check balance
const balance = await db.getBalance(req.user.id);
if (balance < amount) {
return res.status(400).json({ error: 'Insufficient funds' });
}
// TIME GAP HERE - attacker sends many requests simultaneously!
// Deduct and transfer
await db.updateBalance(req.user.id, balance - amount);
await db.updateBalance(toUser, await db.getBalance(toUser) + amount);
});
// With $100 balance, send 50 requests for $100 each
// Many will pass the check before any deduction happens!
Coupon Code Double-Use
Same pattern: check if coupon is used, then mark it as used. With concurrent requests, multiple orders can use the same coupon.
How to Prevent Race Conditions
app.post('/transfer', async (req, res) => {
const { amount, toUser } = req.body;
await db.transaction(async (tx) => {
// Lock the row with FOR UPDATE
const result = await tx.query(
'SELECT balance FROM users WHERE id = $1 FOR UPDATE',
[req.user.id]
);
if (result.rows[0].balance < amount) {
throw new Error('Insufficient funds');
}
// Atomic update
await tx.query(
'UPDATE users SET balance = balance - $1 WHERE id = $2',
[amount, req.user.id]
);
await tx.query(
'UPDATE users SET balance = balance + $1 WHERE id = $2',
[amount, toUser]
);
});
});
How do I test for race conditions?
Send many concurrent requests using tools like curl with parallel or custom scripts. Look for inconsistent state after the requests complete. Burp Suite has a race condition testing feature.
Does JavaScript single-threading prevent races?
No. While JS is single-threaded, async operations can interleave. Between await calls, other requests can modify shared state. Always use atomic operations for critical sections.
Test for Race Conditions
Our scanner helps identify potential race condition vulnerabilities.
Start Free Scan