Skip to content

VNX-820: Missing Synchronization

A Java object that one instance serves every request thread (a class extending HttpServlet/GenericServlet/HttpFilter, a servlet filter extending OncePerRequestFilter/GenericFilterBean or implementing javax/jakarta Filter, a Servlet or HandlerInterceptor implementation, or a Spring @RestController/@Controller/@Service/@Component/@Repository singleton) keeps mutable state in a field and a request-handling method writes it with no synchronization: an assignment, compound assignment or ++/-- of a non-final, non-volatile field, or a mutating call (put, add, remove, clear, merge, compute*, append...) on a field holding a HashMap, ArrayList, HashSet, LinkedList, TreeMap, LinkedHashMap, ArrayDeque or StringBuilder, declared with that type or declared final as a Map/List/Set and given one in a constructor. Concurrent requests then race on it (lost updates, corrupted collections, one user's data shown to another). Not reported: writes inside a synchronized method or synchronized block, writes while an explicit Lock taken in the method (lock()/writeLock().lock()) is still held, Atomic*, Concurrent*, CopyOnWrite*, ThreadLocal, Collections.synchronized* and volatile fields, injected fields (@Autowired/@Inject/@Value/@Resource), writes in constructors, static initialisers, init()/afterPropertiesSet()/@PostConstruct methods and setters, locals and parameters that shadow the field, classes that are not shared (entities, DTOs), beans scoped prototype/request/session, test files and comments.

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

Overview

VNX-820 maps to CWE-820: Missing Synchronization. Servlets and Spring singletons are shared by every request thread; a field written from a request handler without a lock is a data race.

What Gets Flagged

public class HitServlet extends HttpServlet {
    private int hits;
    private String lastUser;
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        hits++;                                   // FLAGGED
        lastUser = req.getParameter("user");      // FLAGGED: one user's value seen by another
    }
}

@Component
public class SessionCache {
    private final Map<String, String> sessions = new HashMap<>();
    public void remember(String id, String user) {
        sessions.put(id, user);                   // FLAGGED: HashMap mutated concurrently
    }
}

Not flagged: ConcurrentHashMap/AtomicInteger fields, writes inside synchronized, constructor and init() writes, @Scope("prototype") beans, locals that shadow the field.

// FLAGGED: a classic servlet Filter shares one instance
public class RequestCounterFilter implements Filter {
    private long served;
    public void doFilter(ServletRequest rq, ServletResponse rs, FilterChain c) {
        served++;
    }
}

Not flagged: writes made between lock.lock() and lock.unlock() on a ReentrantLock field.

Remediation

  1. Keep per-request data in locals or the request/session, not in fields.
  2. Use concurrent types (ConcurrentHashMap, AtomicLong, LongAdder) for shared counters and caches.
  3. Guard compound updates with synchronized or a 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-820
// nosec vnx-820

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

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