VNX-833: Deadlock
Detects lock-order inversion in Java: one path takes lock A then B while another path in the same file takes B then A, through nested synchronized blocks, synchronized instance methods or explicit lock() calls.
| Field | Value |
|---|---|
| Rule ID | VNX-833 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Java |
| CWE | CWE-833 |
| 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 | deadlock lock-ordering concurrency cwe-833 |
| Source | internal/sast/rules/vnx-833.rego |
Overview
VNX-833 maps to CWE-833: Deadlock. The most common deadlock in application code is a lock-order inversion: one method takes lock A and, while holding it, takes lock B; another method takes B and then A. When two threads run the two methods at once, each holds the lock the other waits for, and neither ever proceeds.
The rule reads nested synchronized (x) blocks, instance synchronized methods (which hold this for their body) and explicit x.lock() calls (ReentrantLock and similar, held until x.unlock()) in each Java file, records every “acquire B while holding A” pair, and reports the inner acquisition of any pair whose reverse also appears in the file.
What Gets Flagged
synchronized (accountsLock) {
synchronized (auditLock) { // FLAGGED: accountsLock -> auditLock
audit.record(from, to, amount);
}
}
// ... elsewhere in the same file
synchronized (auditLock) {
synchronized (accountsLock) { // FLAGGED: auditLock -> accountsLock
e.apply();
}
}
What Is Not Flagged
- Nested locks always taken in the same order.
- Locks taken one after the other (released before the next is acquired).
static synchronizedmethods, and an inner lock taken inside a task handed to another thread (executor.submit(() -> { ... }),new Thread(...), aTimerTask).- Inversions whose two halves are in different files, and the pattern in comments or string literals.
Remediation
Define one global order for the locks and acquire them in that order everywhere, for example by ordering on a stable key (account.id) before nesting. Where possible, hold one lock at a time, or use tryLock with a timeout and back off.
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-833
// nosec vnx-833
Or record an ignore rule: vulnetix ignore add --rule vnx-833 --reason "...". See Suppressing findings.