Skip to content

VNX-821: Incorrect Synchronization

Java code synchronizes, but on a monitor that does not give the intended mutual exclusion. Reported: synchronized (new X()) (a fresh lock each call, so nothing is excluded); synchronized on a local variable assigned new ... in the same method; synchronized (Thread.currentThread()) (each thread locks itself); synchronized on a string literal, Boolean.TRUE/FALSE, Integer/Long/String.valueOf or .intern(), or a String/Integer/Long/Short/Byte/Boolean/Character field or variable, final or not (interned and cached values are shared with unrelated code); synchronized (getClass()) (a subclass instance locks a different Class object); synchronized on a java.util.concurrent Lock/ReentrantLock/ReadWriteLock/StampedLock/Semaphore object, field or local (its intrinsic monitor is unrelated to lock()/unlock()); synchronized on a non-final field that a method other than a constructor reassigns (threads end up holding different monitors); and a write to a static non-final field inside a non-static synchronized method, which locks the instance while the data is shared by every instance. Not reported: synchronized (this), on a final Object or collection field, on X.class, on a non-final field assigned only in a constructor, on a local obtained from a shared map or a lock-stripe array, static synchronized methods, a static write inside a synchronized (X.class) block, comments and strings.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-821
Severity Low
SARIF level note
Kind sast
Languages Java
CWE CWE-821
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L
Tags lock-sync cwe-821 concurrency
Source internal/sast/rules/vnx-821.rego

Overview

VNX-821 maps to CWE-821: Incorrect Synchronization. The code takes a lock, but the lock object makes the synchronization useless or shares it with unrelated code.

What Gets Flagged

synchronized (new Object()) { n--; }          // FLAGGED: a new monitor every call

Object lock = new Object();
synchronized (lock) { ... }                   // FLAGGED: local lock

synchronized ("cache") { size++; }            // FLAGGED: interned literal shared JVM-wide
synchronized (Boolean.TRUE) { ... }           // FLAGGED
synchronized (getClass()) { ... }             // FLAGGED: subclasses lock a different object

private final ReentrantLock lock = new ReentrantLock();
synchronized (lock) { ... }                   // FLAGGED: use lock.lock()/unlock()

private final String LOCK = "LOCK";
synchronized (LOCK) { ... }                   // FLAGGED: interned String

private static int total;
public synchronized void add(int n) {
    total += n;                               // FLAGGED: instance lock, static data
}

Not flagged: synchronized (this), synchronized (lock) on a private final Object lock = new Object(), synchronized (Foo.class), static synchronized methods.

// FLAGGED: every thread locks itself
synchronized (Thread.currentThread()) { entries.add(amount); }

Not flagged: a non-final lock field assigned only in the constructor, and total++ inside synchronized (Registry.class) within an instance-synchronized method.

Remediation

  1. Lock on a dedicated private final Object field (static when the data is static).
  2. Use lock()/unlock() on java.util.concurrent locks, never their monitor.
  3. Lock static state on the class (Foo.class) or a static final lock.

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-821
// nosec vnx-821

Or record an ignore rule: vulnetix ignore add --rule vnx-821 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-821.rego, cli/internal/sast/docs/vnx-821.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.