How can Perl prompt for a password without showing it in the terminal?

To use Term::ReadKey, this works:

sub prompt_for_password {
    require Term::ReadKey;

    # Tell the terminal not to show the typed chars
    Term::ReadKey::ReadMode('noecho');

    print "Type in your secret password: ";
    my $password = Term::ReadKey::ReadLine(0);

    # Rest the terminal to what it was previously doing
    Term::ReadKey::ReadMode('restore');

    # The one you typed didn't echo!
    print "\n";

    # get rid of that pesky line ending (and works on Windows)
    $password =~ s/\R\z//;

    # say "Password was <$password>"; # check what you are doing :)

    return $password;
}

You can also use IO::Prompter:

$ perl -MIO::Prompter -wE '$pass = prompt("Password: ", -echo => "*"); $pass =~ s/\R\z//; say $pass'

It is probably overkill for just asking for the password, but it is useful if you need to elicit other types of user input as well. Note that you do need Term::ReadKey for the password masking function to work. Unfortunately, the module does not warn you about this at build time. You will know you are in this situation if the one-liner above generates the warning:

Warning: next input will be in plaintext

The prompt() subroutine was called with the -echo flag, but the Term::ReadKey module was not available to implement this feature. The input will proceed as normal, but this warning is issued to ensure that the user doesn't type in something secret, expecting it to remain hidden, which it won't.

How that warning message corresponds to the meaning given in the explanation is beyond me, but, oh well.

Note that on Windows the module leaves a CR at the end of the input string which chomp does not remove (because it is looking for a CRLF sequence). That's why I use \R in the example above. See RT #118255.