sec(739): enumeration through login screen#746
Merged
diogomartino merged 2 commits intoJul 4, 2026
Merged
Conversation
|
nice catch on timing hadn't thought of that at all |
Contributor
Author
|
@h8d13 yeah, it was kinda obvious, in the tests on my production server it was ~10x when the user existed (40ms vs 400ms) |
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.
Closes #739 the three user-enumeration vectors i found.
Vectors patched
{ errors: { identity: "Invalid credentials" } }. Thepassword-field error and the invite-specific message are gone.existingUser.bannedcheck is moved afterBun.password.verify. Without valid credentials the response is indistinguishable from any other failure; the ban reason is still visible to the legitimate account owner.Bun.password.verifyagainst a precomputed dummy hash is run in the unknown-identity branch, matching the latency (~100–500 ms) of the known-identity path.Technical decisions
GENERIC_LOGIN_ERRORconstant — single shared string across the three failure branches to prevent drift via typo.Bun.password.hashruns once on the first miss and is reused. If the hash creation rejects, a.catchresets the cached promise so a transient failure cannot turn into a new vector (500 = unknown vs 400 = known).Tests
identity: "Invalid credentials"(previouslypassword: "Invalid password").Side fix
Minor inconsistencies in the client spanish translations (
apps/client/src/i18n/locales/es/disconnected.json,settings.json) spotted during diagnosis.