VNX-488: Exposure of Data Element to Wrong Session
Per-request or per-user data stored in a field of a Java component that one instance serves every request: a class that extends HttpServlet/GenericServlet, is annotated @WebServlet, @Controller or @RestController, or extends a Struts Action. A request handler assigns a non-final field (instance or static) from the request (getParameter, getHeader, getAttribute, getSession, getRemoteUser, getUserPrincipal, getCookies, getInputStream/getReader, getQueryString), directly or through a local variable assigned from the request a few lines above. Concurrent requests share the field, so one user's data is served to another. Not reported: locals, final fields, assignments in init() or a constructor, fields of classes that are not request singletons (including Spring beans annotated @RequestScope, @SessionScope or @Scope request/session/prototype), fields set from servlet configuration, and the pattern in comments or string literals.
| Field | Value |
|---|---|
| Rule ID | VNX-488 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Java |
| CWE | CWE-488 |
| 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 | servlet shared-state session race-condition cwe-488 |
| Source | internal/sast/rules/vnx-488.rego |
Overview
VNX-488 maps to CWE-488: Exposure of Data Element to Wrong Session. It reports request data written into a field of a servlet or Spring controller, which one instance shares across all requests.
Why This Matters
The container creates one servlet instance, and Spring creates one controller instance, and every request thread runs through it at once. A field set from request A can be read while serving request B, so one user sees another user’s name, account or cart.
What Gets Flagged
public class ProfileServlet extends HttpServlet {
private String userName;
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
userName = request.getParameter("user"); // FLAGGED
response.getWriter().println(render(userName));
}
}
@RestController
public class CartController {
private static String lastUser;
@GetMapping("/cart")
public Cart cart(HttpServletRequest req) {
String user = req.getRemoteUser();
lastUser = user; // FLAGGED
...
Not flagged: the same value kept in a local variable, a final field, or a field set in init() from servlet configuration.
Remediation
- Keep per-request data in local variables or pass it as method arguments.
- Store per-user data in the request (
request.setAttribute) or the session, never in a field of the servlet or controller. - If a component must hold per-request state, make it request-scoped (
@RequestScope) rather than a singleton.
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-488
// nosec vnx-488
Or record an ignore rule: vulnetix ignore add --rule vnx-488 --reason "...". See Suppressing findings.