VNX-935: Administrative endpoint declared without a function-level access check
Reports a Spring or JAX-RS handler mapped to an admin, management or staff path and explicitly opened to everyone with @PermitAll / permitAll(). Unguarded admin routes in Python are VNX-306, in JavaScript, TypeScript and Go VNX-425.
| Field | Value |
|---|---|
| Rule ID | VNX-935 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Java, Kotlin |
| CWE | CWE-935 |
| 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 | access-control authorization cwe-935 |
| Source | internal/sast/rules/vnx-935.rego |
Overview
VNX-935 maps to CWE-935: OWASP Top Ten 2013 Category A7 - Missing Function Level Access Control. The category has no code shape of its own. This rule reports the one only an annotation can produce: a Spring or JAX-RS handler, in Java or Kotlin, mapped to a path that names an administrative function (/admin, /administrator, /superadmin, /sysadmin, /management, /manage, /backoffice, /staff) and annotated @PermitAll, @PreAuthorize("permitAll()"), @Secured("IS_AUTHENTICATED_ANONYMOUSLY") or @AnonymousAllowed, which opens it to every caller.
What Gets Flagged
@GetMapping("/admin/users")
@PreAuthorize("permitAll()") // flagged: opens an admin function to everyone
public List<User> list() { ... }
Not flagged: Spring handlers without such an annotation (Spring Security is configured centrally; VNX-931 judges that configuration), handlers that require a role (@PreAuthorize("hasRole('ADMIN')")), non-administrative paths, test files, comments and strings. Authorization enforced in another module (a gateway, a global filter) is not visible to the rule.
Reported by other rules, so one route is one finding:
- An administrative Flask, FastAPI or Quart route with nothing in front of it is reported by VNX-306.
- An administrative Express, Koa, Fastify or Go route with nothing in front of it is reported by VNX-425.
Remediation
Require the administrator role on the server for every administrative function, and never open one with permitAll:
@GetMapping("/admin/users")
@PreAuthorize("hasRole('ADMIN')")
public List<User> list() { ... }
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-935
// nosec vnx-935
Or record an ignore rule: vulnetix ignore add --rule vnx-935 --reason "...". See Suppressing findings.