From 9c852e8385f1829e1bba26cfec86a4b57624972e Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Sun, 30 Aug 2026 03:31:01 +0000 Subject: [PATCH] fix(vault): drop the 12-character master password minimum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting up or recovering a vault refused any master password shorter than 12 characters, which blocked passwords that were perfectly usable. The length check is gone from both paths; only an empty password is refused now, since an empty master password derives a useless key. The strength meter keeps rating length — anything under 8 characters still reads as Weak — but it no longer tells you to use at least 12, and nothing it says blocks the form. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01MrHcQXSjCeCcAKhWPZg8w9 --- apps/extension/__tests__/vault-ui.test.js | 12 ++++++++--- .../popup/components/vault/VaultUnlock.jsx | 21 ++++++++++--------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/apps/extension/__tests__/vault-ui.test.js b/apps/extension/__tests__/vault-ui.test.js index 736887c..4d85024 100644 --- a/apps/extension/__tests__/vault-ui.test.js +++ b/apps/extension/__tests__/vault-ui.test.js @@ -83,10 +83,16 @@ describe('assessPassword', () => { expect(assessPassword('')).toMatchObject({ score: 0, label: '' }); }); - it('calls out a password that is simply too short', () => { + it('rates a very short password weak without demanding a minimum length', () => { const result = assessPassword('Ab1!xy'); - expect(result.label).toBe('Too short'); - expect(result.hint).toMatch(/at least 12/); + expect(result.label).toBe('Weak'); + expect(result.hint).not.toMatch(/at least/); + }); + + it('accepts an eleven-character password as a normal rating', () => { + const result = assessPassword('5stringerSS'); + expect(result.label).toBe('Fair'); + expect(result.score).toBeGreaterThanOrEqual(3); }); it('rates a long mixed password highly', () => { diff --git a/apps/extension/src/popup/components/vault/VaultUnlock.jsx b/apps/extension/src/popup/components/vault/VaultUnlock.jsx index 732b29f..5990fdc 100644 --- a/apps/extension/src/popup/components/vault/VaultUnlock.jsx +++ b/apps/extension/src/popup/components/vault/VaultUnlock.jsx @@ -9,23 +9,24 @@ import React, { useState } from 'react'; * background/vault-session.js. */ -const MIN_PASSWORD_LENGTH = 12; - /** Rough strength read, shown while choosing a master password. */ export function assessPassword(password) { const value = String(password || ''); if (value.length === 0) return { score: 0, label: '', hint: '' }; + // Length still dominates the rating, but it no longer gates anything: a short + // master password reads as weak and is accepted all the same. + if (value.length < 8) { + return { score: 1, label: 'Weak', hint: 'Short passwords are easy to guess' }; + } + let score = 0; - if (value.length >= MIN_PASSWORD_LENGTH) score += 1; + if (value.length >= 8) score += 1; if (value.length >= 16) score += 1; if (/[a-z]/.test(value) && /[A-Z]/.test(value)) score += 1; if (/\d/.test(value)) score += 1; if (/[^A-Za-z0-9]/.test(value)) score += 1; - if (value.length < MIN_PASSWORD_LENGTH) { - return { score: 1, label: 'Too short', hint: `Use at least ${MIN_PASSWORD_LENGTH} characters` }; - } if (score <= 2) return { score: 2, label: 'Weak', hint: 'Add length, or a mix of characters' }; if (score === 3) return { score: 3, label: 'Fair', hint: '' }; if (score === 4) return { score: 4, label: 'Good', hint: '' }; @@ -149,8 +150,8 @@ export function VaultUnlock({ exists, onSetup, onUnlock, onRecover, onUnlocked } let res; if (mode === 'setup') { - if (password.length < MIN_PASSWORD_LENGTH) { - setError(`Use at least ${MIN_PASSWORD_LENGTH} characters`); + if (password.length === 0) { + setError('Enter a master password'); setBusy(false); return; } @@ -166,8 +167,8 @@ export function VaultUnlock({ exists, onSetup, onUnlock, onRecover, onUnlocked } return; } } else if (mode === 'recover') { - if (password.length < MIN_PASSWORD_LENGTH) { - setError(`Use at least ${MIN_PASSWORD_LENGTH} characters`); + if (password.length === 0) { + setError('Enter a master password'); setBusy(false); return; }