VNX-645: Overly Restrictive Account Lockout Mechanism
Reports login code that locks or disables an account once a failed-attempt counter reaches a threshold, in a file that gives the lock no expiry, and django-axes AXES_COOLOFF_TIME = None. Locks with an expiry and administrator deactivation are not reported.
| Field | Value |
|---|---|
| Rule ID | VNX-645 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | JavaScript / TypeScript, Python |
| CWE | CWE-645 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | account-lockout denial-of-service authentication cwe-645 |
| Source | internal/sast/rules/vnx-645.rego |
Overview
VNX-645 maps to CWE-645: Overly Restrictive Account Lockout Mechanism. It reports a statement that locks or disables an account (user.is_locked = True, user.active = false, { locked: true }) on the line of, or just after, a comparison of a failed-login counter with a threshold, when nothing in the file ever lets the lock expire. It also reports AXES_COOLOFF_TIME = None in django-axes settings.
Why This Matters
A permanent lockout turns the lockout into a denial-of-service. An attacker who knows or guesses usernames sends a few bad passwords for each and locks every account until an administrator intervenes.
What Gets Flagged
if user.failed_attempts >= MAX_ATTEMPTS:
user.is_locked = True # no locked_until anywhere
AXES_COOLOFF_TIME = None
if (user.loginAttempts > 5) {
user.active = false;
}
Not flagged: the same lock with user.locked_until = timezone.now() + timedelta(minutes=15) or user.lockUntil = Date.now() + LOCK_TIME, AXES_COOLOFF_TIME = timedelta(minutes=30), an administrator deactivating a user, and test code.
Remediation
- Make the lock expire: store a lock-until time and refuse logins only until then, increasing the delay on repeated lockouts.
- Prefer throttling by client (IP address or device) plus CAPTCHA over locking the account itself.
- Notify the account owner when a lockout happens.
References
- CWE-645: Overly Restrictive Account Lockout Mechanism
- OWASP Authentication Cheat Sheet: Account Lockout
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-645
// nosec vnx-645
Or record an ignore rule: vulnetix ignore add --rule vnx-645 --reason "...". See Suppressing findings.