Skip to content

VNX-306: Missing Authentication for Critical Function

A Python (Flask, FastAPI, Quart) route with an administrative path registered with no authentication decorator, dependency or check. The same defect in JavaScript, TypeScript and Go is VNX-425.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-306
Severity High
SARIF level error
Kind sast
Languages Python
CWE CWE-306
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:H/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:H/DI:H/EX:H/EC:N/P:H
Tags missing-auth critical-function cwe-306
Source internal/sast/rules/vnx-306.rego

Overview

VNX-306 maps to CWE-306: Missing Authentication for Critical Function. It reports an administrative Python route registered with nothing in front of it. A path is administrative when one of its segments is admin, administrator(s), administration, adminpanel/adminarea/adminconsole/admindashboard/adminapi, backoffice, superuser, sysadmin, staff or manage/management.

Reported:

  • a Flask, Quart or FastAPI route decorator (@app.route, @bp.get/post/put/patch/delete, @router.api_route, @app.websocket, also with the path on the line after an open decorator) when none of the other decorators is an auth decorator (login_required, *_required, roles_*, a name with auth, login, admin, role, permission, jwt, token, protect or guard), the route has no dependencies=, the function takes no Security() parameter and no Depends() on an auth-named dependency, and the first 15 lines of the view never test the user (current_user, g.user, session[...], request.authorization, is_admin, abort(401/403), HTTPException(401/403)), in a file with no before_request hook and no APIRouter(dependencies=...);
  • app.add_url_rule("/admin/...", view_func=f) where f is defined in the same file with no such decorator or check.

Why This Matters

Admin routes delete users, change configuration and reset data. Without authentication they are reachable by anyone who guesses or finds the path, and admin paths are among the first that scanners try.

What Gets Flagged

# FLAGGED
@app.route("/admin/users/<int:user_id>/delete", methods=["POST"])
def delete_user(user_id):
    ...

# FLAGGED: Depends(get_db) opens a session, it does not authenticate
@router.delete("/api/admin/tenants/{tenant_id}")
async def drop_tenant(tenant_id: str, db=Depends(get_db)):
    ...

What Is Not Flagged

  • @app.route("/admin/users") followed by @login_required, async def drop_tenant(..., admin=Depends(require_admin)), dependencies=[Depends(require_admin)].
  • A view that checks the user in its first lines, and files with a before_request hook or router-wide dependencies.
  • The pages an administrator uses before logging in (/admin/login, /admin/logout, /admin/forgot-password, /admin/static, /admin/health).
  • Django admin.site.urls (the Django admin enforces staff login), non-administrative paths, test files and comments.

Reported by other rules, so one route is one finding:

  • An administrative Express, Koa, Fastify or Go route with nothing in front of it is reported by VNX-425.
  • A Spring or JAX-RS handler that @PermitAll opens to everyone is reported by VNX-935.

Remediation

  1. Put an authentication and role check in front of every admin route: a decorator or a FastAPI dependency.
  2. Prefer protecting the whole admin prefix in one place (a blueprint before_request, a router with dependencies=[...]) so a new route cannot be added unprotected.

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

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

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