Skip to content

fix(auth): skip the too long password check on plugin logins - #7828

Merged
Chocobozzz merged 4 commits into
Chocobozzz:developfrom
dlarochette:fix/password-grant-plugin-bypass-too-long-check
Nov 5, 2026
Merged

Chocobozzz merged 4 commits into
Chocobozzz:developfrom
dlarochette:fix/password-grant-plugin-bypass-too-long-check

Conversation

@dlarochette

@dlarochette dlarochette commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #7829

Problem

handlePasswordGrant rejects any password over the bcrypt limit (50
characters / 72 bytes) before knowing how the user will be
authenticated. On the id-and-pass plugin path (LDAP, SAML, etc.) the
password is validated by the plugin itself and never reaches bcrypt,
so the check rejects valid credentials without protecting anything on
that path.

A production log shows the plugin succeeding and the request failing
4ms later:

12:36:03.891  Login success with auth method ldap of plugin peertube-plugin-auth-ldap for david.larochette.
12:36:03.895  too_long_password: Password is too long. Please reset it using the password reset procedure.

The fix

Move the check into getUserOrThrow, immediately before
user.isPasswordMatch() -- the only place a password is actually
compared with bcrypt on the login path. This naturally excludes the
plugin path (which returns before reaching that line) without needing
to special-case it.

While auditing the other two places that compare a password with
bcrypt (usersCheckCurrentPasswordFactory and the /users/me
password-update validator), I found both call
user.isPasswordMatch(currentPassword) directly, bypassing length
validation entirely. A currentPassword over 72 bytes there reaches
comparePassword, which throws a plain Error instead of returning a
clean too_long_password response. Fixed the same way at both sites.

This is not a security fix: comparePassword has its own guard that
throws above 72 bytes rather than letting bcrypt silently truncate and
compare a prefix, so there is no bypass either before or after this
change. It's a correctness fix (reject a long password with a clean,
typed error instead of either skipping validation entirely on the
plugin path, or crashing with an untyped error on the two
currentPassword paths).

Unrelated to #7344 (raising the 50-character limit) -- that's a
deliberate product constraint tighter than the 72-byte bcrypt limit,
and this PR doesn't touch it.

Tests

  • unit (server-helpers/password.ts): isUserPasswordTooLong
    character-count vs byte-count boundaries, and a pinning test that
    comparePassword itself refuses (throws on) anything over 72 bytes
    rather than truncating
  • integration (plugins/id-and-pass-auth.ts): a plugin login with a
    167-byte password now succeeds; a local login with a 305-byte
    password still returns a clean too_long_password
  • integration (check-params/user-me.ts,
    check-params/two-factor.ts): an over-long currentPassword on
    PUT /users/me and on the two-factor request endpoint both now
    return a clean 400 too_long_password instead of an unhandled error

All 11 CI jobs pass on this branch.

@dlarochette
dlarochette force-pushed the fix/password-grant-plugin-bypass-too-long-check branch from 4a1ebfc to 98a6040 Compare October 15, 2026 14:54
handlePasswordGrant rejected any password over the bcrypt limit before
knowing how the user would be authenticated. On the id-and-pass plugin
path the password is validated by the plugin itself and never reaches
bcrypt, so the check rejected valid credentials without protecting
anything on that path.

Move the check into getUserOrThrow, immediately before
user.isPasswordMatch(), which is the only place a password is compared
with bcrypt on the login path.

Test: the id-and-pass-auth plugin test now logs in with a password
over the bcrypt limit, and confirms a local account still gets a
clean too_long_password error instead of silently falling through.
usersCheckCurrentPasswordFactory and the /users/me password update
validator both call user.isPasswordMatch(currentPassword) directly,
without going through getUserOrThrow. A currentPassword over 72 bytes
reaches comparePassword, which throws a plain Error instead of
returning a clean too_long_password response.

Add the same isUserPasswordTooLong check at both call sites, gated
on the account being local (it is for update-me; explicit for the
factory, where a plugin account takes a different branch already).

Tests:
- unit: isUserPasswordTooLong/isUserPasswordValid boundary cases
  (char count vs byte count), and a pinning test for comparePassword's
  own 72-byte guard (it throws rather than letting bcrypt silently
  truncate and compare a prefix)
- integration: too long currentPassword on PUT /users/me and on the
  two-factor request endpoint now both return a clean 400
  too_long_password instead of an unhandled error
@dlarochette
dlarochette force-pushed the fix/password-grant-plugin-bypass-too-long-check branch from 98a6040 to e4f1e9f Compare October 15, 2026 15:23
@dlarochette dlarochette changed the title Remove password length check for auth plugins fix(auth): skip the too long password check on plugin logins Oct 15, 2026
@Chocobozzz
Chocobozzz merged commit f21bc1b into Chocobozzz:develop Nov 5, 2026
22 checks passed
@Chocobozzz

Copy link
Copy Markdown
Owner

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PeerTube imposes its password size even with an auth plugin

2 participants