Safeguard
Application Security•

CWE-821 Incorrect Synchronization: Locks That Do Not Protect

A lock in the wrong place is as bad as no lock. CWE-821 covers shared resources that are synchronized, but not correctly. Here is what to check.

Safeguard Security Team
2 min read

CWE-821 covers code that uses a shared resource concurrently and does try to synchronize access, but gets it wrong. The lock exists, yet the protection has a hole.

It is not language specific. If your code uses locks, mutexes, monitors or similar tools, this can be you.

How it happens

MITRE describes the result: the resource may not be in the state the product expects, which can lead to unexpected or insecure behavior, especially if an attacker can influence the shared resource. The record does not list specific causes, but common shapes are easy to recognize.

  • Locking only the write path while readers go unprotected.
  • Using two different locks for the same data.
  • Releasing a lock between a check and the action that depends on it.
  • Locking an object that is replaced, so threads hold different locks.
// Vulnerable: a new lock object per call, so nothing is excluded
void update() {
    Object lock = new Object();
    synchronized (lock) {
        counter++;
    }
}

Each thread locks its own private object. The synchronized keyword is there, and it protects nothing.

What an attacker gains

The record lists impact on integrity and confidentiality: modifying application data, reading application data and altering execution logic.

How to find it

MITRE lists automated static analysis (SAST), which models data flow in source or compiled code and can find some instances. Back it up with code review focused on one question per shared variable: which single lock guards it, and is every access inside that lock?

How to fix it

The record lists no formal mitigations, so apply general rules.

  1. Pick one lock per piece of shared state and document it.
  2. Hold the lock across the entire check and update.
  3. Make the lock itself a long lived field, not a local.
  4. Cover readers as well as writers.
private final Object lock = new Object();
void update() {
    synchronized (lock) { counter++; }
}

Quick check

Why can a lock still fail to protect shared data?

A lock only helps if every thread uses the same lock for every access. Different lock objects, or unlocked readers, leave the data exposed.

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.