Solved "Invalid username or pasword": passwords starting with a dash (-) break mkpasswd

Continuing the discussion from Invalid username or password on login (deprecated crypt package) (python3.13.3 breaking):

Hi everyone,

After spending way too long debugging this, I wanted to share what finally solved it for me, because it’s a pretty sneaky edge case that I haven’t seen mentioned in this thread yet.

TL;DR: My admin password started with a hyphen (e.g. -Hes123456), and that was the entire cause of the “Invalid username or password” loop after upgrading to v1.10.5.

How I found it:

Following the suggestions here, I started testing v-check-user-password manually and also ran mkpasswd directly against the hash stored in /etc/shadow:

mkpasswd "my-password" 'HASH_FROM_SHADOW'

It failed every time with:

Method not supported by crypt(3).
Error: password missmatch

But then, out of pure frustration, I tried a different password (one that didn’t start with -) and it worked instantly. That’s when it clicked: mkpasswd was interpreting the leading -H in my password as a command-line option, not as part of the password string.

This is classic Unix argument parsing. When you run:

mkpasswd "-Hes123456" "$hash"

the tool sees -Hes123456 as a flag, tries to parse it, fails, and either bails out or produces a garbage hash. Hence the cryptic Method not supported by crypt(3) error, which has nothing to do with the actual hash method and everything to do with argument parsing.

Why it worked before and not now:

The old v-check-user-password used a small Python snippet with crypt.crypt(), which treats the password as a plain data string and is completely immune to this problem. The new version in v1.10.5 calls mkpasswd directly, which is sensitive to how its arguments are parsed. Combined with the fact that mkpasswd’s argument handling has become stricter over time, this turned into a perfect storm for anyone whose password happens to start with a dash.

How to verify you’re hitting this:

# Check if your password starts with a dash
# Then test mkpasswd manually against your hash:
grep "^admin:" /etc/shadow | cut -d: -f2
mkpasswd "your-password-here" 'hash-from-above'

If it fails only for passwords starting with -, you’ve found it.

Workarounds:

  1. Change your password to one that doesn’t start with a dash via v-change-user-password admin 'NewPassword'. This is the quickest fix.

  2. Patch the script to use -- as a separator, which tells mkpasswd that everything after it is a literal argument, not an option:

    In /usr/local/hestia/bin/v-check-user-password, change:

    hash=$(mkpasswd "$password" "$shadow")
    

    to:

    hash=$(mkpasswd -- "$password" "$shadow")
    

    The -- is the standard POSIX way to say “end of options, everything after this is data”. This is the proper fix and I’d love to see it merged upstream.

Suggestion for the Hestia team:

If anyone from the dev team is reading this, adding -- before "$password" in v-check-user-password would make the script robust against this edge case and save other users from the same multi-hour debugging session I just went through. It’s a one-character fix with zero downsides.

Hope this helps someone else!

Thanks for reporting it.