fix #167: Validate rounds format to prevent NaN bypass#168
Open
thesmart wants to merge 2 commits intodcodeIO:mainfrom
Open
fix #167: Validate rounds format to prevent NaN bypass#168thesmart wants to merge 2 commits intodcodeIO:mainfrom
thesmart wants to merge 2 commits intodcodeIO:mainfrom
Conversation
These tests currently FAIL, exposing a potential vulnerability where non-numeric round values in salt strings bypass bcrypt's work factor. The vulnerability: - Salt like "$2b$xx$..." causes parseInt to return NaN - NaN bypasses rounds validation (NaN < 4 and NaN > 31 are both false) - 1 << NaN becomes 1 << 0 = 1, reducing bcrypt to a single round - This makes the resulting hash trivially crackable Red Tests added: - invalidRoundsNaNProducesWeakHash: hash contains "$NaN$" - invalidRoundsNaN: fully non-numeric rounds "xx" - invalidRoundsNaNAsync: async version via callback - invalidRoundsPartialNaN: partial non-numeric "1x" **Severity: LOW** In most real-world scenarios, salts come from genSalt() which always produces valid output. The malformed salt would have to come from: - A buggy application - Corrupted data - Deliberately malicious input to compare()
The fix validates that rounds contains exactly 2 digits before parsing, rejecting malformed salts with a clear error message. Red tests are now green: - invalidRoundsNaN: fully non-numeric rounds "xx" - invalidRoundsNaNAsync: async version via callback - invalidRoundsPartialNaN: partial non-numeric "1x" - validRoundsLeadingZero: rounds can start with 0 - invalidRoundsZero: 0 rounds are rejected - invalidRounds32: 32 rounds are rejected Updated tests: - invalidRoundsNaNProducesWeakHash: invalid rounds throw
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Non-numeric characters in the rounds position (e.g.,
$2b$xx$...) causes parseInt to return NaN, which bypasses security validation and reduced bcrypt to a single round.Fixes #167
Location
index.jslines 1078-1080:The Bug
When non-numeric characters are in the rounds position,
parseIntreturnsNaN:rounds = NaN + NaN = NaNif (rounds < 4 || rounds > 31)→ PASSES (NaN comparisons are false)rounds = (1 << rounds) >>> 0→1 << NaN=1 << 0= 1 round only!Red tests added to demonstrate issue:
The Fix
The fix validates that rounds contains exactly 2 digits before parsing, rejecting malformed salts with a clear error message.
Severity: LOW
In most real-world scenarios, salts come from genSalt() which always produces valid output. The malformed salt would have to come from:
The real value of this fix is: