[{"data":1,"prerenderedAt":138},["ShallowReactive",2],{"blog-vulnerabilities/race-conditions":3},{"id":4,"title":5,"body":6,"category":118,"date":119,"dateModified":119,"description":120,"draft":121,"extension":122,"faq":123,"featured":121,"headerVariant":124,"image":123,"keywords":123,"meta":125,"navigation":126,"ogDescription":127,"ogTitle":123,"path":128,"readTime":129,"schemaOrg":130,"schemaType":131,"seo":132,"sitemap":133,"stem":134,"tags":135,"twitterCard":136,"__hash__":137},"blog/blog/vulnerabilities/race-conditions.md","Race Conditions Explained",{"type":7,"value":8,"toc":108},"minimark",[9,16,21,26,41,45,48,52,61,77,96],[10,11,12],"tldr",{},[13,14,15],"p",{},"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.",[17,18,20],"h2",{"id":19},"common-race-condition-examples","Common Race Condition Examples",[22,23,25],"h3",{"id":24},"double-spend-in-wallet-applications","Double-Spend in Wallet Applications",[27,28,30],"code-block",{"label":29},"Vulnerable: check-then-update pattern",[31,32,37],"pre",{"className":33,"code":35,"language":36},[34],"language-text","app.post('/transfer', async (req, res) => {\n  const { amount, toUser } = req.body;\n\n  // Check balance\n  const balance = await db.getBalance(req.user.id);\n  if (balance \u003C amount) {\n    return res.status(400).json({ error: 'Insufficient funds' });\n  }\n\n  // TIME GAP HERE - attacker sends many requests simultaneously!\n\n  // Deduct and transfer\n  await db.updateBalance(req.user.id, balance - amount);\n  await db.updateBalance(toUser, await db.getBalance(toUser) + amount);\n});\n\n// With $100 balance, send 50 requests for $100 each\n// Many will pass the check before any deduction happens!\n","text",[38,39,35],"code",{"__ignoreMap":40},"",[22,42,44],{"id":43},"coupon-code-double-use","Coupon Code Double-Use",[13,46,47],{},"Same pattern: check if coupon is used, then mark it as used. With concurrent requests, multiple orders can use the same coupon.",[17,49,51],{"id":50},"how-to-prevent-race-conditions","How to Prevent Race Conditions",[27,53,55],{"label":54},"Safe: using database transactions",[31,56,59],{"className":57,"code":58,"language":36},[34],"app.post('/transfer', async (req, res) => {\n  const { amount, toUser } = req.body;\n\n  await db.transaction(async (tx) => {\n    // Lock the row with FOR UPDATE\n    const result = await tx.query(\n      'SELECT balance FROM users WHERE id = $1 FOR UPDATE',\n      [req.user.id]\n    );\n\n    if (result.rows[0].balance \u003C amount) {\n      throw new Error('Insufficient funds');\n    }\n\n    // Atomic update\n    await tx.query(\n      'UPDATE users SET balance = balance - $1 WHERE id = $2',\n      [amount, req.user.id]\n    );\n    await tx.query(\n      'UPDATE users SET balance = balance + $1 WHERE id = $2',\n      [amount, toUser]\n    );\n  });\n});\n",[38,60,58],{"__ignoreMap":40},[62,63,64,71],"faq-section",{},[65,66,68],"faq-item",{"question":67},"How do I test for race conditions?",[13,69,70],{},"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.",[65,72,74],{"question":73},"Does JavaScript single-threading prevent races?",[13,75,76],{},"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.",[78,79,80,86,91],"related-articles",{},[81,82],"related-card",{"description":83,"href":84,"title":85},"Another timing-based issue","/blog/vulnerabilities/timing-attacks","Timing Attacks",[81,87],{"description":88,"href":89,"title":90},"Related auth bypass","/blog/vulnerabilities/idor","IDOR",[81,92],{"description":93,"href":94,"title":95},"Transactions and locking","/blog/best-practices/database","Database Best Practices",[97,98,101,105],"cta-box",{"href":99,"label":100},"/","Start Free Scan",[17,102,104],{"id":103},"test-for-race-conditions","Test for Race Conditions",[13,106,107],{},"Our scanner helps identify potential race condition vulnerabilities.",{"title":40,"searchDepth":109,"depth":109,"links":110},2,[111,116,117],{"id":19,"depth":109,"text":20,"children":112},[113,115],{"id":24,"depth":114,"text":25},3,{"id":43,"depth":114,"text":44},{"id":50,"depth":109,"text":51},{"id":103,"depth":109,"text":104},"vulnerabilities","2026-01-21","Race conditions let attackers exploit timing gaps between check and use. Learn how TOCTOU bugs work and how to prevent them with proper locking and atomicity.",false,"md",null,"red",{"noindex":126},true,"Learn how race condition vulnerabilities work and how to prevent them.","/blog/vulnerabilities/race-conditions","6 min read","[object Object]","TechArticle",{"title":5,"description":120},{"loc":128},"blog/vulnerabilities/race-conditions",[],"summary_large_image","dVmItqWXeP16-N_aSz2EpocerraWXZBK_0jt0jnA_w4",1775843926483]