How to validate passwords against a zxcvbn score floor, not composition rules
- Step 1Pick the score floor your policy will enforce — Decide the threshold before testing: score 3 is a reasonable floor for ordinary online accounts behind rate limiting; score 4 for admin, VPN, or any account whose hash might end up in a breach dump. zxcvbn's score is the coarse bucket — you will sanity-check it against the crack-time rows next.
- Step 2Assemble a representative test set — Collect a sample of passwords your current rule would accept —
Summer2024!,Company1!,Welcome123, plus a strong passphrase as a control. Audit each one to see how many your existing composition rule lets through. There is no batch mode, so paste them one at a time. - Step 3Audit each candidate and read the score first — Paste a password into the single
passwordfield. The findings summary shows the 0–4 score and the four crack-time figures. Anything below your chosen floor is what the new policy will reject and the old one accepted. - Step 4Cross-check against the offline-fast crack-time row — Don't trust the score alone for borderline cases. Read
offline_fast_hashing_1e10_per_second— a password can read score 3 yet fall in seconds offline if it is short. For a privileged-account floor, require both score 4 and a multi-year offline-fast figure. - Step 5Capture the matched patterns for help-desk guidance — Note the
sequencepatterns on failures —dictionary:passwords,spatial,date,repeat. These become concrete user-facing messages ('your password is a known common password' / 'this is a keyboard pattern') instead of the vague 'increase complexity'. - Step 6Document the floor and wire screening into account creation — Write the chosen score floor into your standard. To actually enforce it at scale in your own signup flow you would integrate zxcvbn directly or call the server-safe API per password (synthetic test passwords only — see the API spoke). For protecting any real exported credentials, hand them to aes-256-encryptor.
How a composition rule compares to a zxcvbn score floor
The same candidates judged by the legacy 'upper+lower+digit+symbol, 8 chars' rule versus zxcvbn 4.4.2. The composition rule passes several offline-trivial passwords.
| Candidate | Composition rule | zxcvbn score | offline-fast crack time | Verdict at a score-3 floor |
|---|---|---|---|---|
P@ssw0rd1 | PASS (all classes, 9 chars) | 0–1 | less than a second | Rejected |
Summer2024! | PASS | 2 | less than a second | Rejected |
Welcome123 | FAIL (no symbol) | 1 | less than a second | Rejected |
Company1! | PASS | 1–2 | less than a second | Rejected |
correct horse battery staple | FAIL (no digit/symbol) | 4 | centuries | Accepted |
river-otter-velvet-9-canyon | PASS | 4 | centuries | Accepted |
Suggested score floors by account class
A starting point for a written standard. Always confirm the offline-fast crack-time row for high-value accounts rather than trusting the coarse score alone.
| Account class | Suggested zxcvbn floor | Extra check | Rationale |
|---|---|---|---|
| Low-risk / public-facing, rate-limited login | score 3 | throttled-online row > 'years' | Attacker is limited to slow online guessing |
| Standard employee / SSO account | score 3–4 | offline-slow row > 'years' | Hash may be bcrypt/Argon2 if breached |
| Admin / VPN / database / privileged | score 4 | offline-fast row > 'years' | Worst case: unsalted dump on a GPU rig |
| Service / API credential | n/a (generate random 32+) | use a manager, not a human password | No memorability requirement — maximise length |
Cookbook
Real zxcvbn 4.4.2 outputs for the kinds of passwords a corporate composition rule lets through, plus the strong controls a score floor should accept. Crack times are the verbatim crack_times_display strings; guesses_log10 is rounded.
The password that ticks every composition box: P@ssw0rd1
Upper, lower, digit, symbol, nine characters — a clean pass on the legacy rule. zxcvbn reverses the leet substitutions, matches it to the common-password list, and scores it 0–1. This single example is usually enough to retire the old rule.
Input: P@ssw0rd1 zxcvbn report (abridged): score: 1 guesses_log10: 4.0 sequence: [ "dictionary:passwords" ] crack_times_display: online_throttling_100_per_hour: 4 days offline_fast_hashing_1e10_per_second: less than a second feedback.warning: "This is similar to a commonly used password" feedback.suggestions: - Predictable substitutions like '@' instead of 'a' don't help very much - Add another word or two. Uncommon words are better.
The seasonal classic IT sees every quarter: Summer2024!
A composition-rule pass that everyone resets to in Q3. zxcvbn matches a common-password root plus a cheap year/date, so it lands at score 2 and dies instantly offline. Rejected by any sensible floor.
Input: Summer2024! zxcvbn report (abridged): score: 2 guesses_log10: 7.44 sequence: [ "dictionary:passwords", "bruteforce" ] (2024 = cheap date) crack_times_display: online_throttling_100_per_hour: 31 years offline_fast_hashing_1e10_per_second: less than a second feedback.warning: "This is similar to a commonly used password" feedback.suggestions: - Add another word or two. Uncommon words are better.
Fails composition, passes the floor: correct horse battery staple
No digit and no symbol, so the legacy rule blocks it — yet it is the strongest of the lot. A score-3 or score-4 floor accepts it, which is the whole point of switching policies.
Input: correct horse battery staple zxcvbn report (abridged): score: 4 guesses_log10: 20.33 sequence: [ dictionary, bruteforce, dictionary, ... ] crack_times_display: online_throttling_100_per_hour: centuries offline_fast_hashing_1e10_per_second: centuries feedback.warning: "" feedback.suggestions: []
A privileged-account candidate that needs the offline check: J0hn-Donnelly!1990
It reaches score 4 on the coarse bucket, but it is built from a name and a year and is fairly short. For an admin floor, require the offline-fast row to be years — here it isn't, so reject despite the headline 4.
Input: J0hn-Donnelly!1990 zxcvbn report (abridged): score: 4 guesses_log10: 11.0 sequence: [ dictionary:surnames, bruteforce, date ] crack_times_display: online_throttling_100_per_hour: centuries offline_fast_hashing_1e10_per_second: 7 minutes Verdict at an admin floor (score 4 AND offline-fast > years): REJECT
A generator-style passphrase that clears every floor: river-otter-velvet-9-canyon
Four uncommon words with a digit and separators. Passes composition AND audits at score 4 with centuries on every row — the kind of secret your policy should actively encourage.
Input: river-otter-velvet-9-canyon zxcvbn report (abridged): score: 4 guesses_log10: 18.0 sequence: [ dictionary, bruteforce, dictionary, bruteforce, dictionary ] crack_times_display: online_throttling_100_per_hour: centuries offline_fast_hashing_1e10_per_second: centuries feedback.warning: "" feedback.suggestions: []
Edge cases and what actually happens
Empty input — nothing pasted
RejectedAn empty password field throws Enter a password to audit. in the browser tool (the API path throws Provide a password via options.password or request body.). There is no default candidate — a policy test always needs an explicit string.
Candidate contains the employee's own name, username, or email
Not detected herezxcvbn supports a user_inputs dictionary (name, email, username) so it can penalise identity-based passwords — but this tool calls zxcvbn with the password only and passes no user-context list. So jsmith2024 is scored against generic dictionaries, not flagged as 'contains your username'. A real signup-flow integration should pass user_inputs; treat any personal-data password as weaker than the score shown here.
Score 4 but a short, fast-offline candidate
ExpectedThe 0–4 score is a coarse bucket, so a shortish random or name-based string can read score 4 while offline_fast_hashing_1e10_per_second shows minutes. This is why a privileged-account floor should require both score 4 AND a multi-year offline-fast figure, not the headline number alone.
Composition-compliant password scoring 0–1
By designP@ssw0rd1, Company1!, and similar tick every character-class box yet score 0–1 because zxcvbn reverses leet substitutions and matches the common-password list before crediting the substitution. This is the central evidence for abandoning composition rules — not a tool error.
Dictionaries are frozen at the zxcvbn 4.4.2 release (2017-era)
Known limitationzxcvbn 4.4.2 ships fixed word lists. A password riffing on a post-2017 meme or breach won't be flagged as common even though attackers now know it. The score is a strong lower bound on weakness — useful for a floor — but never treat 'score 4' as proof a password isn't already in a modern breach list. Pair the policy with a live breach-screening service for internet-facing accounts.
Trying to upload a CSV of passwords to validate in bulk
Not supportedThis is a single-field, text-only tool — no file drop, no batch validation UI. To screen a corpus you would script the server-safe API one password per call (synthetic/test data only). For hashing or comparing files instead of scoring passwords, see multi-hash-fingerprinter or file-integrity-monitor.
Keyboard-walk password like 1qaz2wsx
By designMatches the spatial pattern and is scored as one cheap token, not random characters. 1qaz2wsx and qwerty12345 look mixed-class but land at score 0–1 — exactly the candidates a composition rule waves through and a score floor rejects.
Auditing a live password via the API for policy testing
Transmitted by designThe slug is server-safe, so an API call sends the password to the server, which runs zxcvbn and returns score, crackTime, feedback, and guesses. That is appropriate for automated policy regression tests on synthetic passwords. Never pipe a real employee credential through the API — the browser tool is the only path that keeps the secret on the device (the field is marked secret).
Setting a maximum-length cap in your policy
Discouraged by NISTzxcvbn parses passphrases of any length fine (calc_time stays in single-digit ms), and NIST SP 800-63B advises against low max-length caps because they block strong passphrases. If your policy enforces an unusually low maximum, the tool will still score long inputs correctly — the limitation is your policy, not the auditor.
Frequently asked questions
What zxcvbn score should our password policy require?
A score-3 floor is reasonable for ordinary online accounts behind rate limiting; require score 4 for admin, VPN, database, or any account whose hash could end up in a breach dump. For high-value accounts, also require the offline_fast_hashing_1e10_per_second crack time to be 'years' or more, because the 0–4 score is a coarse bucket and a short candidate can read 4 yet fall in minutes offline.
Is replacing composition rules with zxcvbn actually NIST-compliant?
It aligns with NIST SP 800-63B's intent. The guideline explicitly recommends dropping composition rules, favouring length and memorable passphrases, and screening new passwords against commonly-used/breached lists. zxcvbn's common-password dictionary performs a lightweight version of that screening. To fully match the guideline, pair a zxcvbn score floor with a live breach-check service, since zxcvbn's lists are frozen at its 4.4.2 release.
Can I validate a whole spreadsheet of passwords at once?
Not in the browser tool — it has a single password field and no file or batch mode. For a corpus you would script the server-safe API, one password per call, suitable for synthetic or test data only. Never run real employee credentials through any automated path; audit those on the device with the browser tool, which never transmits the value.
Why does P@ssw0rd1 pass our complexity rule but fail zxcvbn?
Composition rules count character classes; zxcvbn estimates guessability. It reverses predictable substitutions (@→a, 0→o, 1→i) before matching against the common-password list, so P@ssw0rd1 resolves to a known common password and scores 0–1 with 'less than a second' offline. The feedback even states that substitutions and capitalisation 'don't help very much'.
Does the tool flag passwords built from an employee's name or email?
Not in this implementation. zxcvbn can take a user_inputs list to penalise identity-based passwords, but this tool calls zxcvbn with the password alone and passes no user context. So jsmith2024 is scored against generic dictionaries only. A production signup integration should supply user_inputs; here, assume any personal-data password is weaker than its score suggests.
How do I justify a specific floor to auditors or stakeholders?
Use the numbers the tool returns. Audit a representative sample, record the score, guesses_log10, and the four crack_times_display rows for each, and show how many candidates your old composition rule accepted that fall below your proposed floor. The raw guesses count gives a defensible, non-colour-coded basis for the threshold in a written standard.
Should service and API credentials follow the same floor?
No — they should be generated random secrets of 32+ characters stored in a vault, not human-chosen passwords. There's no memorability constraint, so maximise length and randomness instead of targeting a zxcvbn score. zxcvbn will rate such strings as pure bruteforce; for a long random token the offline-fast row will already be centuries.
Are there file-size or tier limits for policy testing?
No. This is a text-input tool — you paste a password string, not a file — so the security file-size caps (Free 10 MB / 1 file, Pro 100 MB / 5 files, and so on) don't apply. The auditor is on the Free tier and needs no sign-in, so a policy pilot costs nothing.
How current are zxcvbn's common-password lists?
They are frozen at the zxcvbn 4.4.2 release (2017-era). A password based on a newer meme or breach won't be flagged as common even though attackers may know it. Treat the score as a strong lower bound on weakness, not a guarantee of strength, and pair the policy with live breach screening for internet-facing accounts.
What do the four crack-time rows tell a policy author?
They model four attacker speeds: online_throttling_100_per_hour (rate-limited login), online_no_throttling_10_per_second (no limit / stuffing), offline_slow_hashing_1e4_per_second (leaked bcrypt/Argon2 hashes), and offline_fast_hashing_1e10_per_second (unsalted dump on a GPU). Match the row to the threat each account class faces — privileged accounts should be judged on the offline-fast row.
Can users game the score with a keyboard pattern like 1qaz2wsx?
No. zxcvbn matches keyboard walks as the spatial pattern and scores them as a single cheap token, so 1qaz2wsx and qwerty12345 land at score 0–1 despite mixing letters and digits. These are precisely the inputs a composition rule accepts and a zxcvbn floor rejects.
Where do I go after the policy is set, for the credentials we export?
If you export a credential list or a key, protect it before it leaves your control. Use aes-256-encryptor (Web Crypto AES-GCM with PBKDF2 100k) for files and pgp-message-signer to sign distribution messages. To verify exported files haven't been altered, file-integrity-monitor compares two copies byte-for-byte.
Privacy first
Every JAD Security operation runs entirely in your browser. Files, passwords, and PGP private keys never leave your device — verified by zero outbound network requests during processing.