Safeguard
Application Security•

CWE-366 Race Condition Within a Thread: Shared State Hazards

CWE-366 is two threads using the same resource at once, leaving state undefined. See the pattern in Java and the locking fix MITRE recommends.

Safeguard Security Team
3 min read

CWE-366, Race Condition within a Thread, covers two threads of execution using a resource at the same time. The resource may be used while it is in an invalid state, and the state of execution becomes undefined.

It applies to C, C++, Java and C#, according to the MITRE record, and really to any threaded program that shares data.

How it happens

A shared object is read by one thread while another changes it. Or one thread frees or tears down a resource while a second still holds a reference to it. Neither thread is wrong in isolation. The bug is in the overlap.

The observed example is CVE-2022-2621, a chain in which two threads in a web browser use the same resource, but one of them can destroy the resource before the other is done with it.

MITRE sums up the core problem this way: if a lock is overcome, data could be altered in a bad state.

What an attacker gains

MITRE lists integrity impact: altered execution logic and an unexpected state. In practice, a reproducible race can turn into corrupted data or a crash, and in memory unsafe languages a use after free can be worse. An attacker who can trigger the timing repeatedly has the advantage, since they only need to win occasionally.

How to find it

MITRE notes static analysis can find some instances of this weakness. Add these checks.

  • List every piece of mutable state reachable from more than one thread.
  • For each one, name the lock that guards it. If you cannot, that is a finding.
  • Run tests under thread sanitizers where your toolchain supports them, and stress test with many concurrent callers.

How to fix it

MITRE's recommended solution is locking. Use a locking mechanism around code that alters or reads persistent data in a multithreaded environment. If no locking mechanism exists, create resource locking validation checks, using flags and signals to enforce your own blocking while another thread uses the resource.

A Java example. The vulnerable version lets two threads interleave:

class Cache {
    private Map<String, String> map = new HashMap<>();

    void put(String k, String v) { map.put(k, v); }   // not safe
    String get(String k)         { return map.get(k); }
}

A guarded version serializes access:

class Cache {
    private final Map<String, String> map = new HashMap<>();

    synchronized void put(String k, String v) { map.put(k, v); }
    synchronized String get(String k)         { return map.get(k); }
}

For heavier use, a concurrent collection built for the purpose is a better choice. The principle is the same: every access to shared state goes through one guard.

Quick check

What does MITRE call the recommended solution?

Use locking functionality around code that alters or reads persistent data in a multithreaded environment.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.