@sentinel-password/core
v1.3.1
Published
Modern, zero-dependency TypeScript password validation with bloom filter-based common password detection. 100% test coverage (enforced); ~6.3 KB gzipped (10 KB CI limit).
Maintainers
Readme
@sentinel-password/core
Modern TypeScript password validation library with zero dependencies, comprehensive validation rules, and rich feedback.
Documentation | Interactive Playground | API Reference
Features
- Zero Dependencies - No external dependencies, tree-shakeable, ~5.5KB gzipped
- TypeScript-First - Full type safety with strict mode enabled
- Rich Feedback - Actionable suggestions for password improvement
- Comprehensive Validation - 7 built-in validators covering OWASP best practices
- Flexible API - Zero-config defaults with full customization options
- Framework Agnostic - Works in Node.js, browsers, and any JavaScript environment
Installation
npm install @sentinel-password/corepnpm add @sentinel-password/coreyarn add @sentinel-password/coreQuick Start
import { validatePassword } from '@sentinel-password/core'
const result = validatePassword('MySecure!Pass_w0rd')
if (result.valid) {
console.log('Password is valid!')
console.log(`Strength: ${result.strength}`) // 'very-strong'
console.log(`Score: ${result.score}`) // 4
} else {
// `feedback.warning` is always equal to `feedback.suggestions[0]` — the
// first failure, surfaced for prominent display. Iterate `suggestions`
// for the full list; the first entry is the warning.
console.log('Password is invalid')
result.feedback.suggestions.forEach(suggestion => {
console.log(`- ${suggestion}`)
})
}Validation Result
The validatePassword function returns a comprehensive validation result:
interface ValidationResult {
// Overall validation status
valid: boolean
// Strength scoring
score: 0 | 1 | 2 | 3 | 4
strength: 'very-weak' | 'weak' | 'medium' | 'strong' | 'very-strong'
// User feedback
feedback: {
warning?: string // Primary warning message
suggestions: readonly string[] // All improvement suggestions
}
// Individual check results
checks: {
length: boolean // Meets length requirements
characterTypes: boolean // Meets character type requirements
repetition: boolean // No excessive repeated characters
sequential: boolean // No three characters with consecutive charCodeAt values (abc, 123, xyz, plus runs like '!"#' or '9:;')
keyboardPattern: boolean // No keyboard patterns (qwerty, asdf)
commonPassword: boolean // Not in top 1K common passwords (Bloom filter, ~0.84% false-positive rate)
personalInfo: boolean // Doesn't contain personal information
}
}Configuration Options
Customize validation rules to match your requirements:
const result = validatePassword('Tr0ub4dor&3-isLong!', {
// Length constraints
minLength: 12, // default: 8
maxLength: 128, // default: 128
// Character requirements
requireUppercase: true, // default: false
requireLowercase: true, // default: false
requireDigit: true, // default: false
requireSymbol: true, // default: false
// Pattern detection
maxRepeatedChars: 3, // default: 3
checkSequential: true, // default: true
checkKeyboardPatterns: true, // default: true
checkCommonPasswords: true, // default: true
// Personal information exclusion
personalInfo: ['johndoe', '[email protected]'],
})
// result.valid === true, result.strength === 'very-strong'Usage Examples
Basic Validation
import { validatePassword } from '@sentinel-password/core'
// Valid password
const result1 = validatePassword('Tr0ub4dor&3')
console.log(result1.valid) // true
console.log(result1.strength) // 'very-strong'
// Invalid password (too short)
const result2 = validatePassword('pass')
console.log(result2.valid) // false
console.log(result2.feedback.warning) // 'Password must be at least 8 characters'Custom Requirements
import { validatePassword } from '@sentinel-password/core'
// Require strong passwords with all character types
const result = validatePassword('password', {
minLength: 12,
requireUppercase: true,
requireLowercase: true,
requireDigit: true,
requireSymbol: true
})
console.log(result.valid) // false
console.log(result.checks.length) // false
console.log(result.checks.characterTypes) // false
console.log(result.checks.commonPassword) // false — 'password' is in the common-password list
console.log(result.feedback.suggestions)
// [
// 'Password must be at least 12 characters',
// 'Password must contain at least one uppercase letter, digit, symbol',
// 'Password is too common. Please choose a more unique password.'
// ]The character-type validator returns a single combined message listing every missing type — not one suggestion per missing type. Note that 'password' also trips the common-password check, so a third suggestion always appears regardless of length and character-type settings.
Blocking Personal Information
import { validatePassword } from '@sentinel-password/core'
const result = validatePassword('alice2024', {
personalInfo: ['alice', '[email protected]']
})
console.log(result.valid) // false
console.log(result.checks.personalInfo) // false
console.log(result.feedback.warning)
// 'Password contains personal information'Detecting Common Patterns
import { validatePassword } from '@sentinel-password/core'
// Sequential patterns
const result1 = validatePassword('password123')
console.log(result1.checks.sequential) // false
// Keyboard patterns
const result2 = validatePassword('qwerty2024')
console.log(result2.checks.keyboardPattern) // false
// Common passwords
const result3 = validatePassword('password')
console.log(result3.checks.commonPassword) // false
// Excessive repetition
const result4 = validatePassword('passssword')
console.log(result4.checks.repetition) // falseSignup Form Example
import { validatePassword } from '@sentinel-password/core'
function handleSignup(formData: {
email: string
username: string
password: string
}) {
const result = validatePassword(formData.password, {
minLength: 10,
requireUppercase: true,
requireLowercase: true,
requireDigit: true,
personalInfo: [formData.email, formData.username]
})
if (!result.valid) {
return {
success: false,
errors: result.feedback.suggestions
}
}
return {
success: true,
passwordStrength: result.strength
}
}Advanced Usage
Individual Validators
For fine-grained control, import and use individual validators:
import {
validateLength,
validateCharacterTypes,
validateRepetition,
validateSequential,
validateKeyboardPattern,
validateCommonPassword,
validatePersonalInfo
} from '@sentinel-password/core'
const password = 'MyPassword123'
// Check individual constraints
const lengthCheck = validateLength(password, { minLength: 12 })
console.log(lengthCheck.passed) // false
console.log(lengthCheck.message) // 'Password must be at least 12 characters'
const charTypeCheck = validateCharacterTypes(password, {
requireUppercase: true,
requireLowercase: true,
requireDigit: true,
requireSymbol: true,
})
console.log(charTypeCheck.passed) // false
console.log(charTypeCheck.message) // 'Password must contain at least one symbol'
// (one combined message listing every missing type — not one message per type)Character Type Helpers
import {
hasUppercase,
hasLowercase,
hasDigit,
hasSymbol
} from '@sentinel-password/core'
const password = 'MyPassword123!'
console.log(hasUppercase(password)) // true
console.log(hasLowercase(password)) // true
console.log(hasDigit(password)) // true
console.log(hasSymbol(password)) // trueTypeScript
The library is written in TypeScript with full type definitions included:
import type {
ValidationResult,
ValidatorOptions,
ValidatorCheck,
StrengthScore,
StrengthLabel,
CheckId
} from '@sentinel-password/core'
const options: ValidatorOptions = {
minLength: 10,
requireUppercase: true
}
const result: ValidationResult = validatePassword('test', options)
const score: StrengthScore = result.score // 0 | 1 | 2 | 3 | 4
const strength: StrengthLabel = result.strength // 'very-weak' | 'weak' | ...Validation Rules
1. Length Validation
- Default: 8-128 characters
- Configurable via
minLengthandmaxLength
2. Character Types
- Optional requirements for uppercase, lowercase, digits, and symbols
- Configurable via
requireUppercase,requireLowercase,requireDigit,requireSymbol
3. Repetition Detection
- Blocks excessive repeated characters (e.g., "aaaa")
- Default: max 3 repeated characters
- Configurable via
maxRepeatedChars
4. Sequential Pattern Detection
- Blocks any three characters whose
charCodeAtvalues are consecutive ascending or descending —abc,123,xyzplus less-obvious runs like!"#,,-.,9:;(equivalent to consecutive Unicode code points for the BMP, which covers every character a typical password uses) - Works forward and backward
- Configurable via
checkSequential
5. Keyboard Pattern Detection
- Blocks runs along common keyboard layouts: QWERTY (
qwerty,asdfgh,zxcvbn), AZERTY (azerty,qsdfg), QWERTZ (qwertz,yxcvb), Dvorak (aoeu,htns), Colemak (arst,dhne), and Cyrillic (йцукен,фывап) - Catches numeric runs: full top row (
1234567890), reverse (0987654321), and numeric-keypad rows/columns (789,456,123,741,852,963) - Does not match the shifted symbol row (
!@#$%…) — only unshifted runs - Configurable via
checkKeyboardPatterns
6. Common Password Detection
- Blocks the top 1,000 most common passwords
- Uses a Bloom filter for efficient memory usage (~1.5 KB vs ~8 KB for the raw list)
- No false negatives (every password in the list is rejected) and a ~0.84% false-positive rate — uncommon passwords are very rarely flagged as "common"
- Configurable via
checkCommonPasswords
7. Personal Information Detection
- Blocks passwords containing personal info (username, email, etc.)
- Extracts username from email addresses
- Configurable via
personalInfoarray
Bundle Size
- ESM: ~16KB uncompressed, ~5.5KB gzipped
- CJS: ~17KB uncompressed, ~6KB gzipped
- Zero dependencies - no additional packages needed
- Tree-shakeable - only import what you use
Runtime Support
The published package is plain ES2022 with no Node or browser-specific APIs, so it runs anywhere those features are available:
- Chrome/Edge 88+
- Firefox 78+
- Safari 14+
- Node.js 18+ (and Deno, Bun, Cloudflare Workers, Vercel Edge — see the Server-Side Usage guide)
Building this monorepo requires Node.js 20+ (
engines.nodeat the repo root). The 18+ minimum above applies to running the published@sentinel-password/corepackage, not to developing it.
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
License
MIT - see LICENSE for details.
Related Packages
@sentinel-password/react- React hook for password validation with debouncing@sentinel-password/react-components- Accessible, headless React components
Acknowledgments
Inspired by zxcvbn and modern password validation best practices from OWASP.
