Skip to content
Authentication Reviewed 2026-09-12

Weak Password Configuration

What does this mean ?

A weak password policy permits easily guessed credentials or makes secure password use unnecessarily difficult. Hardcoded service credentials, insecure password storage and account throttling are related but distinct problems; a complexity regular expression does not solve them all.

What can happen ?

Common or reused passwords can enable account takeover through guessing or credential stuffing. Aggressive lockouts can also deny access to legitimate users. Risks depend on MFA, recovery flows, rate limiting and whether password hashes are exposed.

Recommendation

Use long passwords and support password managers, paste and autofill. NIST SP 800-63B-4 specifies a minimum of 15 characters when a password is the only factor; it permits a minimum of 8 when the password is used as part of MFA. Permit at least 64 characters. A 15-character minimum is a straightforward baseline for a service that may allow password-only sign-in.

Compare new passwords against a blocklist of common, expected and compromised values. Do not require arbitrary mixtures of uppercase, numbers and symbols or periodic changes without evidence of compromise. Normalize supported Unicode consistently before hashing and verification, and never silently truncate.

Add rate limits, appropriate MFA and secure recovery. Store credentials with an adaptive password-hashing library. Keep plaintext passwords out of URLs, analytics, logs and error messages. A function named GetEncryptedPassword does not establish any of these properties.

Sample Code

These helpers demonstrate one explicit 15–128 Unicode-code-point policy after NFC normalization. A limit of 128 is an application choice, not a universal standard. The blocklist is a server-maintained set of normalized exact values; it must not be sent to analytics. This is only enrollment validation. Login uses the stored hash's verification API and the same normalization policy; it must not reject an existing valid password merely because enrollment rules changed.

import unicodedata

def validate_new_password(candidate: str, blocked: set[str]) -> str:
    normalized = unicodedata.normalize("NFC", candidate)
    if not 15 <= len(normalized) <= 128:
        raise ValueError("Use between 15 and 128 characters")
    if normalized in blocked:
        raise ValueError("Choose a password that is not common or compromised")
    return normalized  # Pass directly to a password-hashing library.
function validateNewPassword(candidate, blocked) {
  if (typeof candidate !== 'string') throw new Error('Password required');
  const normalized = candidate.normalize('NFC');
  const length = Array.from(normalized).length;
  if (length < 15 || length > 128) throw new Error('Use between 15 and 128 characters');
  if (blocked.has(normalized)) throw new Error('Choose a different password');
  return normalized;
}

A server-side check is required even if the UI runs the same helper. Use a request-size cap before processing large input.

static String validateNewPassword(String candidate, java.util.Set<String> blocked) {
    if (candidate == null) throw new IllegalArgumentException("Password required");
    String normalized = java.text.Normalizer.normalize(candidate, java.text.Normalizer.Form.NFC);
    int length = normalized.codePointCount(0, normalized.length());
    if (length < 15 || length > 128) {
        throw new IllegalArgumentException("Use between 15 and 128 characters");
    }
    if (blocked.contains(normalized)) throw new IllegalArgumentException("Choose a different password");
    return normalized;
}

Modern .NET; EnumerateRunes avoids counting UTF-16 surrogate pairs twice:

static string ValidateNewPassword(string candidate, ISet<string> blocked)
{
    ArgumentNullException.ThrowIfNull(candidate);
    string normalized = candidate.Normalize(System.Text.NormalizationForm.FormC);
    int length = 0;
    foreach (var rune in normalized.EnumerateRunes()) length++;
    if (length < 15 || length > 128)
        throw new ArgumentException("Use between 15 and 128 characters");
    if (blocked.Contains(normalized)) throw new ArgumentException("Choose a different password");
    return normalized;
}

Import System.Text for rune enumeration. Configure the surrounding identity framework consistently and use its password hasher and rate-limiting flow.

Regression checks

Check the minimum and maximum boundaries, spaces, long passphrases, non-ASCII characters and composed/decomposed Unicode equivalents. Confirm a blocked value is rejected without exposing it in logs. Verify paste/autofill works. Test throttling and recovery separately, including legitimate-user recovery after failed attempts. Store only fictitious test passwords and never collect real passwords as analytics parameters.

References