Skip to content

VNX-703: Optional value read with get() without checking that it is present

Reports Java Optional values unwrapped with get()/getAsInt()/getAsLong()/getAsDouble() without a presence check: findById(...).get() and other Spring Data finders such as findByUsername(...).get(), findFirst().get(), stream max/min(...).get(), OptionalInt max().getAsInt(), and an Optional (or var assigned from a finder) whose get() is not preceded by isPresent()/isEmpty().

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-703
Severity Low
SARIF level note
Kind sast
Languages Java
CWE CWE-703
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 improper-check-exceptional optional cwe-703
Source internal/sast/rules/vnx-703.rego

Overview

VNX-703 maps to CWE-703: Improper Check or Handling of Exceptional Conditions. An empty Optional is an expected outcome: no row has this id, no element matches the filter. get() turns that outcome into an unchecked NoSuchElementException, so a request for an unknown id becomes an HTTP 500 with a stack trace instead of a 404.

The rule reports, in production .java files:

  • Spring Data findById(...).get();
  • findFirst().get() and findAny().get(), including .get() on the next line of a split chain;
  • stream max(...)/min(...) and reduce(X::y) followed by .get();
  • IntStream/LongStream/DoubleStream max()/min()/average()/findFirst() followed by getAsInt/getAsLong/getAsDouble;
  • Optional.ofNullable(...).get();
  • a variable declared Optional<T> (or OptionalInt/OptionalLong/OptionalDouble) whose get() is called within the next 15 lines with no isPresent(), isEmpty(), ifPresent() or null test of it in between or on the same line.

Not reported: orElse, orElseGet, orElseThrow, ifPresent, a presence test before the get(), Map.get, Future.get, List.get, Collections.max(...).get(...), test files, comments and string literals. Optionals passed between methods or stored in fields are not followed.

What Gets Flagged

return orders.findById(id).get();                                   // FLAGGED
return list.stream().max(Comparator.comparing(Order::total)).get(); // FLAGGED

Optional<Account> account = repo.findByLogin(login);
return account.get().getEmail();                                    // FLAGGED

What Is Not Flagged

return orders.findById(id).orElseThrow(() -> new NotFoundException(id));

Optional<Account> a = repo.findByLogin(login);
if (a.isEmpty()) {
    return "";
}
return a.get().getName();

Remediation

  1. Use orElseThrow(() -> new NotFoundException(...)) so the absent case maps to a deliberate error (and a 404).
  2. Use orElse/orElseGet when a default is meaningful, or ifPresent for side effects.

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-703
// nosec vnx-703

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

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