CWE-413 means the product does not lock, or does not correctly lock, a resource when it must have exclusive access. Someone else can then modify the resource while the product is working on it, which breaks the product's assumption that the data would not change.
How it happens
Typical forms are a missing lock around shared state, a lock taken after the check instead of before it, or a lock released too early. Two threads or processes then operate on the same object at once.
Here is a simple Python example of the pattern:
balance = 100
def withdraw(amount):
global balance
if balance >= amount: # check
balance -= amount # use: another thread may run in between
MITRE's observed example is a chain in an operating system kernel where insufficient locking led to a use after free (CVE-2022-20141). Locking bugs often become memory bugs.
What an attacker gains
The record lists integrity and availability: modifying application data, instability, and crashes or restarts.
How to find it
MITRE says static analysis can find some instances by modeling data flow, but not all. Add these:
- Review shared mutable state and ask which lock guards each piece.
- Run tests under thread sanitizers and stress them with parallel requests.
How to fix it
- Hold the lock across the whole check and use sequence.
- Use one lock per resource and a consistent lock order to avoid deadlocks.
- Prefer atomic operations or database transactions over hand rolled locks.
import threading
lock = threading.Lock()
def withdraw(amount):
global balance
with lock:
if balance >= amount:
balance -= amount
Quick check
Is locking the check enough?
No. The lock must cover the use as well, or the state can change between the two.