owasp-password-strength-test, password-validator, and zxcvbn are JavaScript libraries used to enforce password security policies and estimate strength on the client side. password-validator focuses on schema-based rule enforcement using a fluent API. owasp-password-strength-test implements specific OWASP guideline checks using traditional rules. zxcvbn is an entropy-based estimator developed by Dropbox that analyzes patterns and dictionary matches to calculate crack time rather than just checking character requirements.
Choosing the right password validation library impacts both security posture and user experience. owasp-password-strength-test, password-validator, and zxcvbn approach this problem differently — one focuses on compliance rules, one on schema validation, and one on entropy estimation. Let's break down how they handle real-world validation scenarios.
password-validator relies on explicit schema rules you define.
// password-validator: Define explicit rules
const schema = new PasswordValidator();
schema.is().min(8).is().max(100).has().uppercase().has().symbols();
const isValid = schema.validate('MyPass123!');
// Returns true or false based on your schema
owasp-password-strength-test uses a fixed set of OWASP guideline rules.
// owasp-password-strength-test: Fixed OWASP rules
import passwordStrengthTest from 'owasp-password-strength-test';
const result = passwordStrengthTest.test('MyPass123!');
// Returns object with errors and strength level
zxcvbn calculates entropy based on patterns and dictionary matches.
// zxcvbn: Entropy-based estimation
import zxcvbn from 'zxcvbn';
const result = zxcvbn('MyPass123!');
// Returns score 0-4 and estimated crack time
The way you interact with these libraries affects code readability and maintenance.
password-validator uses a fluent interface for building schemas.
// password-validator: Fluent schema
const schema = new PasswordValidator();
schema.is().min(10).has().digits(2);
const details = schema.validate('Pass1', { details: true });
// Returns array of failed requirements if invalid
owasp-password-strength-test exposes a simple test function.
// owasp-password-strength-test: Direct test
import passwordStrengthTest from 'owasp-password-strength-test';
const result = passwordStrengthTest.test('Weak');
console.log(result.errors); // List of failed OWASP checks
zxcvbn is a single function call with optional inputs.
// zxcvbn: Function with context
import zxcvbn from 'zxcvbn';
const result = zxcvbn('Hunter2', ['hunter', 'user123']);
console.log(result.feedback.warning); // "Passwords should not contain personal data"
How you communicate strength to users varies significantly between these tools.
password-validator gives boolean or list of failed rules.
// password-validator: Specific error messages
const errors = schema.validate('short', { details: true });
// [{ name: 'min', arguments: 8 }, ...]
owasp-password-strength-test provides strength levels and error lists.
// owasp-password-strength-test: Strength categories
const result = passwordStrengthTest.test('Password');
console.log(result.strength); // e.g., "weak"
zxcvbn offers natural language feedback and scores.
// zxcvbn: UX-friendly feedback
const result = zxcvbn('correcthorsebatterystaple');
console.log(result.feedback.suggestions); // ["Add another word or two"]
Security teams often debate rule-based checks versus entropy estimation.
password-validator enforces policy but not strength.
// password-validator: Passes predictable patterns
const isValid = schema.validate('Abcd1234!');
// true (meets rules, but weak in practice)
owasp-password-strength-test aligns with audit requirements.
// owasp-password-strength-test: Compliance focused
const result = passwordStrengthTest.test('Abcd1234!');
// May pass OWASP rules despite low entropy
zxcvbn models real-world cracking behavior.
// zxcvbn: Catches predictable patterns
const result = zxcvbn('Abcd1234!');
// Score likely low due to sequence recognition
| Feature | password-validator | owasp-password-strength-test | zxcvbn |
|---|---|---|---|
| Logic | Schema Rules | OWASP Rules | Entropy & Patterns |
| Output | Boolean / Details | Strength Level / Errors | Score 0-4 / Feedback |
| Config | Fluent API | Fixed | Function Args |
| Best For | Policy Enforcement | Compliance Audits | User Security UX |
| Maintenance | Active | Check Status | Industry Standard |
password-validator is your tool for enforcing hard requirements — like "must have 1 symbol" — especially in enterprise forms where policy dictates structure. It works well for immediate input validation but should not be your only line of defense.
owasp-password-strength-test fits niche scenarios where you must demonstrate adherence to specific OWASP checklists during audits. Verify its maintenance status before use — if updates are stale, consider mapping zxcvbn scores to your compliance needs instead.
zxcvbn is the default choice for modern applications. It provides the best user experience by explaining why a password is weak rather than just rejecting it. For maximum security, combine zxcvbn for strength estimation with password-validator for hard policy limits like maximum length or forbidden characters.
Choose owasp-password-strength-test if you need strict compliance with legacy OWASP rule sets without external dependencies. It is suitable for internal enterprise tools where specific regulatory checklists must be met exactly. However, verify current maintenance status before adopting, as newer entropy-based tools often provide better security coverage.
Choose password-validator if your primary goal is enforcing specific composition rules like minimum length, uppercase requirements, or forbidden substrings. It offers a clean fluent interface for defining schemas and is ideal for forms where you need clear boolean validation or detailed error lists based on static rules.
Choose zxcvbn if you want to measure actual password strength based on entropy and common patterns rather than simple character rules. It is the industry standard for user feedback because it discourages predictable passwords like 'Password123!' even if they meet complexity requirements. Use this for consumer-facing apps where security UX matters.
owasp-password-strength-test is a password-strength tester based off of the
OWASP Guidelines for enforcing secure passwords. It is
lightweight, extensible, has no dependencies, and can be used on the server
(nodejs) or in-browser.
owasp-password-strength-test is not an OWASP project - it is merely based off
of OWASP research.
From the command line:
npm install owasp-password-strength-test
Within your document:
<script src='owasp-password-strength-test.js'></script>
This module is built upon the following beliefs:
Passwords should be subject to stricter complexity requirements than passphrases.
Thus, the module:
provides for "required" and "optional" tests. In order to be considered "strong", a password must pass all required tests, as well as a configurable number of optional tests. This makes it possible to always enforce certain rules (like minimum password length), while giving users flexibility to honor only some of a pool of lower-priority rules.
encourages the use of passphrases over passwords. Passphrases (by default) are not subject to the same complexity requirements as a password. (Whereby, by default, a "passphrase" can be defined as "a password whose length is greater than or equal to 20 characters.")
can be arbitrarily extended as-needed with additional required and optional tests.
After you've included it into your project, using the module is straightforward:
// require the module
var owasp = require('owasp-password-strength-test');
// invoke test() to test the strength of a password
var result = owasp.test('correct horse battery staple');
// in the browser, including the script will make a
// `window.owaspPasswordStrengthTest` object availble.
var result = owaspPasswordStrengthTest.test('correct horse battery staple');
The returned value will take this shape when the password is valid:
{
errors : [],
failedTests : [],
requiredTestErrors : [],
optionalTestErrors : [],
passedTests : [ 0, 1, 2, 3, 4, 5, 6 ],
isPassphrase : false,
strong : true,
optionalTestsPassed : 4
}
... and will take this shape when the password is invalid:
{
errors: [
'The password must be at least 10 characters long.',
'The password must contain at least one uppercase letter.',
'The password must contain at least one number.',
'The password must contain at least one special character.'
],
failedTests : [ 0, 4, 5, 6 ],
passedTests : [ 1, 2, 3 ],
requiredTestErrors : [
'The password must be at least 10 characters long.',
],
optionalTestErrors : [
'The password must contain at least one uppercase letter.',
'The password must contain at least one number.',
'The password must contain at least one special character.'
],
isPassphrase : false,
strong : false,
optionalTestsPassed : 1
}
Whereby:
errors is an array of strings of error messages associated with the
failed tests.
failedTests enumerates which tests have failed, beginning from 0 with the
first required test
passedTests enumerates which tests have succeeded, beginning from 0 with
the first required test
requiredTestErrors is an array containing the error messages of required
tests that have failed.
optionalTestErrors is an array containing the error messages of optional
tests that have failed.
isPassphrase is a boolean indicating whether or not the password was
considered to be a passphrase.
strong is a boolean indicating whether or not the user's password
satisfied the strength requirements.
optionalTestsPassed is a number indicating how many of the optional tests
were passed. In order for the password to be considered "strong", it (by
default) must either be a passphrase, or must pass a number of optional tests
that is equal to or greater than configs.minOptionalTestsToPass.
The module may be configured as follows:
var owasp = require('owasp-password-strength-test');
// Pass a hash of settings to the `config` method. The settings shown here are
// the defaults.
owasp.config({
allowPassphrases : true,
maxLength : 128,
minLength : 10,
minPhraseLength : 20,
minOptionalTestsToPass : 4,
});
Whereby:
allowPassphrases is a boolean that toggles the "passphrase" mechanism on
and off. If set to false, the strength-checker will abandon the notion of
"passphrases", and will subject all passwords to the same complexity
requirements.
maxLength is a constraint on a password's maximum length.
minLength is a constraint on a password's minimum length.
minPhraseLength is the minimum length a password needs to achieve in order
to be considered a "passphrase" (and thus exempted from the optional
complexity tests by default).
minOptionalTestsToPass is the minimum number of optional tests that a
password must pass in order to be considered "strong". By default (per the
OWASP guidelines), four optional complexity tests are made, and a password
must pass at least three of them in order to be considered "strong".
If you would like to filter passwords through additional tests beyond the
default, you may simply push new tests onto the appropriate arrays within the
module's test object:
var owasp = require('owasp-password-strength-test');
// push "required" tests onto `tests.required` array, and push "optional" tests
// onto the `tests.optional` array.
owasp.tests.required.push(function(password) {
if (password === 'one two three four five') {
return "That's the kind of thing an idiot would have on his luggage!";
}
});
Test functions must resemble the following:
// accept the password as the single argument
function(password) {
// the "if" conditional should evaluate to `true` if the password is bad
if (thePasswordIsBad) {
// On password failure, a string should be returned. It will be pushed
// onto an array of errors associated with the password.
return "This is the failure message associated with the test";
}
// if the password is OK, nothing should be returned
}
To run the module's test suite, cd into its directory and run npm test. You
may first need to run npm install to install the required development
dependencies. (These dependencies are not required in a production
environment, and facilitate only unit testing.)
If you would like to contribute code, please fork this repository, make your changes, and then submit a pull-request.