CWE-662 is the class of mistakes where code lets multiple threads, processes, components or systems use a shared resource that must be used by only one at a time, without properly coordinating them. The result is simultaneous access to something that cannot take it. Anyone writing concurrent code is exposed: servers handling parallel requests, kernels, mobile apps, background workers and distributed systems.
How it happens
Synchronization is the set of mechanisms that let independent threads or processes operate on shared resources in predictable ways. MITRE lists locks, mutexes and semaphores among them. Some operations on a shared resource cannot be done atomically. They take several steps, and those steps must run in sequence with nothing else interfering.
When that guarantee is missing, behavior becomes unpredictable. MITRE says improper synchronization can lead to data or memory corruption, denial of service and similar problems.
The classic shape is check then act:
# Vulnerable: two threads can both pass the check
balance = {"acct": 100}
def withdraw(amount):
if balance["acct"] >= amount: # step 1: check
time.sleep(0) # another thread can run here
balance["acct"] -= amount # step 2: act
Two threads each withdraw 80 from a balance of 100. Both pass the check, and the account ends at negative 60.
The record gives two examples:
- CVE-2021-1782: a chain where improper locking (CWE-667) leads to a race condition (CWE-362), noted in the record as exploited in the wild per CISA KEV.
- CVE-2009-0935: an attacker provides an invalid address to a memory-reading function, causing a mutex to be unlocked twice.
The first shows how this weakness sits above related ones. Improper locking and race conditions are narrower children of the same idea.
What an attacker gains
MITRE lists impact on integrity and confidentiality, with the ability to modify application data, read application data and alter execution logic. In the record's own examples, a race condition was exploited in the wild and a double unlock was reachable by an attacker who supplied an invalid address.
How to find it
The record lists automated static analysis (SAST), which can find some instances by analyzing source code or compiled code without running it. Static tools are good at obvious cases: shared variables written without a lock, locks acquired on one path and not another, double unlocks.
They are weaker on timing. Add these checks:
- Inventory shared mutable state: globals, caches, singletons, files, database rows.
- For each, write down which lock protects it. If the answer is "none" or "it depends", investigate.
- Run tests with many threads and with thread sanitizers or race detectors where your language has them.
- Review any check-then-act sequence on shared data.
How to fix it
MITRE's mitigation is short: use industry standard APIs to synchronize your code. Do not invent your own locking scheme. In plain steps:
- Decide which resources are shared and who owns them.
- Protect the whole multi-step operation, not just one line of it.
- Use the standard library's locks, atomic types or concurrent data structures.
- Prefer designs that avoid sharing: message passing, immutable data, or per-thread copies.
- Keep critical sections small, and always release locks on every path, including errors.
import threading
lock = threading.Lock()
def withdraw(amount):
with lock: # check and act as one step
if balance["acct"] >= amount:
balance["acct"] -= amount
The with block releases the lock even if an exception occurs. For database state, push the check into one atomic statement or a transaction instead of reading, deciding in application code and writing back.
Quick check
Why is a lock around only the write not enough?
The check and the write form one logical operation. Another thread can change the value between them, so both steps need to sit under the same lock.
What does MITRE recommend for implementing synchronization?
Use industry standard APIs rather than custom mechanisms.
Can static analysis find all of these?
It finds some instances. Timing dependent bugs often need stress tests and race detectors as well.