Repository navigation
Bun.password: accept memoryCost below 8 when hashing again #39599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -112,17 +112,12 @@ | |
| }), | ||
| ).toThrow(); | ||
|
|
||
| // argon2 requires `memoryCost >= 8 * parallelism`; Bun hard-codes | ||
| // `parallelism = 1`, so anything below 8 must throw rather than be | ||
| // silently clamped (regression coverage for #30960). | ||
| for (const invalid of [1, 3, 7]) { | ||
| expect(() => | ||
| hash(placeholder, { | ||
| algorithm: "argon2id", | ||
| memoryCost: invalid, | ||
| }), | ||
| ).toThrow("Memory cost must be at least 8"); | ||
| } | ||
| expect(() => | ||
| hash(placeholder, { | ||
| algorithm: "argon2id", | ||
| memoryCost: 0, | ||
| }), | ||
| ).toThrow("Memory cost must be greater than 0"); | ||
|
|
||
| expect(() => | ||
| hash(placeholder, { | ||
|
|
@@ -175,14 +170,14 @@ | |
| algorithm: "argon2id", | ||
| memoryCost: 2 ** 32 + 4608, | ||
| }), | ||
| ).toThrow("Memory cost must be an integer between 8 and 4294967295"); | ||
| ).toThrow("Memory cost must be an integer between 1 and 4294967295"); | ||
|
|
||
| expect(() => | ||
| hash(placeholder, { | ||
| algorithm: "argon2id", | ||
| memoryCost: 8.5, | ||
| }), | ||
| ).toThrow("Memory cost must be an integer between 8 and 4294967295"); | ||
| ).toThrow("Memory cost must be an integer between 1 and 4294967295"); | ||
|
|
||
| // Non-finite values: NaN and -Infinity fail the lower-bound check, | ||
| // +Infinity fails the integer/upper-bound check. | ||
|
|
@@ -196,11 +191,11 @@ | |
| ); | ||
| for (const memoryCost of [NaN, -Infinity]) { | ||
| expect(() => hash(placeholder, { algorithm: "argon2id", memoryCost })).toThrow( | ||
| "Memory cost must be at least 8", | ||
| "Memory cost must be greater than 0", | ||
| ); | ||
| } | ||
| expect(() => hash(placeholder, { algorithm: "argon2id", memoryCost: Infinity })).toThrow( | ||
| "Memory cost must be an integer between 8 and 4294967295", | ||
| "Memory cost must be an integer between 1 and 4294967295", | ||
| ); | ||
| }); | ||
|
|
||
|
|
@@ -345,8 +340,8 @@ | |
| expect(await password.verify("test", hashed)).toBeTrue(); | ||
| }); | ||
|
|
||
| describe.concurrent("argon2 hashes with memoryCost below 8 from earlier Bun versions still verify", () => { | ||
| // Generated by Bun 1.3.14, which accepted memoryCost < 8. | ||
| describe.concurrent("argon2 memoryCost below 8", () => { | ||
| // Generated by Bun 1.3.14. | ||
|
Check warning on line 344 in test/js/bun/util/password.test.ts
|
||
|
Comment on lines
+343
to
+344
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 nit: the adjacent test title Extended reasoning...What's staleThe previous review round flagged four "minimum 8" references. Commit 3ebd546 fixed the three user-facing ones (
After this PR the floor is 1, and after 3ebd546 neither the docs nor the Why re-raise it when the thread is resolvedThe author's follow-up reply enumerated exactly three fixes ("updated all three"), matching the three user-facing references the comment led with. The test title/comment was the trailing "while there" item — the phrasing of the reply suggests it was overlooked rather than consciously declined, and with the thread now marked resolved it won't otherwise resurface. Mentioning the leftover once, as a non-blocking nit, is the lowest-friction way to close the loop. Step-by-step
Addressing the refutationOne verifier argued this is below the standalone reporting threshold: it's a non-user-facing regression-test title whose assertions remain valid, the prior review already surfaced it, and REVIEW.md's "Name things truthfully" targets code identifiers rather than test titles. Taking each point:
The prior review's own reasoning did concede "That's fair" to the below-threshold objection for the test item taken alone — but then bundled it anyway because the three user-facing items justified the comment. Now that those three are fixed and the thread is closed, the calculus is: one lightweight nit vs. leaving a comment that will read as factually wrong to the next person touching this file. The former seems like the smaller cost. Suggested fixPurely wording — e.g. retitle to |
||
| const legacy = { | ||
| argon2id: | ||
| "$argon2id$v=19$m=4,t=1,p=1$jaFm03353WIBtbqnvp4hx6Pd0Pk2keYfomedORTs6bI$Q+62iWiDQhCP3VFQvnMnGptmDAHFQGqY3d/dmRcGVOw", | ||
|
|
@@ -359,19 +354,24 @@ | |
| }; | ||
|
|
||
| for (const [name, hash] of Object.entries(legacy)) { | ||
| test(name, async () => { | ||
| test(`verifies legacy ${name}`, async () => { | ||
| expect(await password.verify("hello", hash)).toBeTrue(); | ||
| expect(await password.verify("hellp", hash)).toBeFalse(); | ||
| expect(password.verifySync("hello", hash)).toBeTrue(); | ||
| expect(password.verifySync("hellp", hash)).toBeFalse(); | ||
| }); | ||
| } | ||
|
|
||
| test("hashing with memoryCost below 8 is still rejected", () => { | ||
| expect(() => password.hashSync("hello", { algorithm: "argon2id", memoryCost: 4 })).toThrow( | ||
| "Memory cost must be at least 8", | ||
| ); | ||
| }); | ||
| for (const memoryCost of [1, 4, 7]) { | ||
| for (const algorithm of ["argon2id", "argon2i", "argon2d"] as const) { | ||
| test(`hashes with ${algorithm} m=${memoryCost} as written`, async () => { | ||
| const hashed = await password.hash("hello", { algorithm, memoryCost, timeCost: 1 }); | ||
| expect(hashed).toStartWith(`$${algorithm}$v=19$m=${memoryCost},t=1,p=1$`); | ||
| expect(await password.verify("hello", hashed)).toBeTrue(); | ||
| expect(await password.verify("hellp", hashed)).toBeFalse(); | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| const defaultAlgorithm = "argon2id"; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.