CWE-1322 describes a product built on a single-threaded, non-blocking model that still contains code which can block when called. If an attacker can reach that code, one request can stall everyone.
How it happens
Single-threaded event loops exist to avoid the resource cost of many threads. MITRE names Python asyncio, Vert.x and Node.js, plus custom event loops. In such a model all code should be non-blocking. If something blocks, the event loop effectively stops, and nothing else gets served.
Blocking code includes expensive computation and blocking library calls, such as exclusive file operations or calls that need a successful network operation. The risk is highest when an attacker can invoke that code directly, or when the blocking is affected by environmental conditions the attacker can influence.
A Python example. The vulnerable handler does a CPU heavy loop and a blocking network call inside an async function.
# Vulnerable: blocks the event loop for every client
import asyncio, requests
async def handler(request):
data = requests.get(request.query["url"]).text # blocking network call
total = sum(i * i for i in range(10**8)) # long CPU loop
return data, total
A safer shape moves both off the loop.
# Safer: use an async client and a worker for CPU work
import asyncio, aiohttp
def heavy():
return sum(i * i for i in range(10**6))
async def handler(request):
async with aiohttp.ClientSession() as s:
async with s.get(request.query["url"], timeout=5) as r:
data = await r.text()
total = await asyncio.get_running_loop().run_in_executor(None, heavy)
return data, total
(Fetching a user-supplied URL has its own risks. The point here is the loop.)
What an attacker gains
The consequence in the record is denial of service through CPU consumption. An unexpected call to blocking code can trigger an infinite loop, or a large loop that makes the software pause and wait indefinitely.
How to find it
The record has no detection methods. Practical checks: look for synchronous file, network and crypto calls inside async handlers, and measure event loop lag under load. Many runtimes have a debug mode that reports slow callbacks.
How to fix it
- Replace blocking calls with non-blocking alternatives used asynchronously.
- Pass expensive computations to worker threads. The right approach depends on the framework.
- Break expensive computations into several smaller ones. Check your framework documentation for guidance.
Quick check
Why does one blocking call affect all users?
There is one thread running the event loop. While blocking code runs, the loop cannot process anything else.