From 9c31da1756104ad07dfa7a87bda94cefc1b7d2ca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:32:12 +0000 Subject: [PATCH] Add comprehensive tests for NIST-aligned password validation Co-authored-by: CommanderStorm <26258709+CommanderStorm@users.noreply.github.com> --- server/password-util.js | 5 +- test/backend-test/test-password-util.js | 101 ++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 test/backend-test/test-password-util.js diff --git a/server/password-util.js b/server/password-util.js index fe99c99e7..60d6241ea 100644 --- a/server/password-util.js +++ b/server/password-util.js @@ -10,14 +10,13 @@ const MIN_PASSWORD_LENGTH = 8; /** * Validates a password according to NIST SP 800-63B guidelines. - * + * * NIST guidelines state: * - Passwords should have a minimum length (8-12 characters recommended) * - Composition rules (requiring specific character types) SHALL NOT be imposed * - All printable ASCII characters and Unicode characters should be allowed - * + * * This implementation enforces only minimum length, allowing all character compositions. - * * @param {string} password - The password to validate * @returns {{ ok: boolean, msg?: string }} Validation result */ diff --git a/test/backend-test/test-password-util.js b/test/backend-test/test-password-util.js new file mode 100644 index 000000000..ec7f4b014 --- /dev/null +++ b/test/backend-test/test-password-util.js @@ -0,0 +1,101 @@ +const { describe, test } = require("node:test"); +const assert = require("node:assert"); + +const { validatePassword, MIN_PASSWORD_LENGTH } = require("../../server/password-util"); + +describe("Password Validation (NIST-aligned)", () => { + test("should reject empty password", () => { + const result = validatePassword(""); + assert.strictEqual(result.ok, false); + assert.match(result.msg, /cannot be empty/i); + }); + + test("should reject null password", () => { + const result = validatePassword(null); + assert.strictEqual(result.ok, false); + assert.match(result.msg, /cannot be empty/i); + }); + + test("should reject undefined password", () => { + const result = validatePassword(undefined); + assert.strictEqual(result.ok, false); + assert.match(result.msg, /cannot be empty/i); + }); + + test("should reject password shorter than minimum length", () => { + const result = validatePassword("short"); + assert.strictEqual(result.ok, false); + assert.match(result.msg, /at least \d+ characters/i); + }); + + test("should accept password exactly at minimum length", () => { + const password = "a".repeat(MIN_PASSWORD_LENGTH); + const result = validatePassword(password); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); + + test("should accept long password with only lowercase letters", () => { + const result = validatePassword("thisisaverylongpassword"); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); + + test("should accept passphrase without numbers or special characters", () => { + const result = validatePassword("CorrectHorseBatteryStaple"); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); + + test("should accept password with mixed case but no numbers", () => { + const result = validatePassword("MySecretPassword"); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); + + test("should accept password with numbers and special characters", () => { + const result = validatePassword("MyP@ssw0rd123"); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); + + test("should accept password with only numbers", () => { + const result = validatePassword("12345678"); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); + + test("should accept password with only special characters", () => { + const result = validatePassword("!@#$%^&*"); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); + + test("should accept password with spaces", () => { + const result = validatePassword("my secure password"); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); + + test("should accept very long password", () => { + const result = validatePassword("a".repeat(100)); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); + + test("minimum password length should be 8 characters", () => { + assert.strictEqual(MIN_PASSWORD_LENGTH, 8); + }); + + test("should accept Unicode characters", () => { + const result = validatePassword("パスワード12345"); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); + + test("should accept emojis in password", () => { + const result = validatePassword("password🔒🔑"); + assert.strictEqual(result.ok, true); + assert.strictEqual(result.msg, undefined); + }); +});