How I Caught a Network Engineer Passing Passwords via SSH Command Line

A sysadmin discovers a colleague passing SSH passwords in plain text via command-line arguments, triggering an audit that reveals widespread insecure practices including passwords exposed in process lists, CI/CD logs, and cron jobs.

There is a long-standing principle: "if something can be done quickly and conveniently, someone will inevitably do it at the expense of security." In infrastructure teams, this is especially noticeable. Network engineers often solve tasks on the fly, and that's great — until it involves passwords. One such case became a lesson for us. At first glance, it seemed trivial, but the consequences could have been much more serious.

How It All Started

An ordinary workday. I was checking the process list on the server (ps aux) and suddenly I see:

sshpass -p 'Qwerty123' ssh admin@10.0.5.21

A password. In plain text. On the command line.

I went up to my colleague:

— What kind of sorcery is this?
— It's a script for quick access, so I don't have to enter the password every time.
— Do you realize that any user on this server can see that password?
— Well, we're inside the network...
— Until someone runs ps or it ends up in logs.

A couple of hours later, we already had an unplanned audit.

Why This Is a Problem

Passing a password in command arguments is a classic anti-pattern.

  • Command arguments are visible in ps, /proc/[PID]/cmdline, Task Manager.
  • They can end up in CI/CD logs.
  • Monitoring and auditing tools will also pick them up.
  • Many utilities (sshpass, plink, WinSCP CLI, rsync, mysql, curl, mRemoteNG) allow passing passwords this way — and it's a temptation for a quick hack.

As a result, you can obtain the password without even touching SSH itself.

How to Search for Such Cases

Windows (PowerShell):

$insecureProcs = Get-CimInstance Win32_Process | Where-Object {
    $_.CommandLine -match '\-p\s' -or
    $_.CommandLine -match '\-pw\s' -or
    $_.CommandLine -match '--password=' -or
    $_.CommandLine -match '/password='
} | Select-Object ProcessId, Name, CommandLine
$insecureProcs | Format-Table -AutoSize

Linux (bash):

ps -eo pid,user,command --no-header | while read PID USER CMD; do
  if [[ "$CMD" =~ -p ]] || [[ "$CMD" =~ -pw ]] || [[ "$CMD" =~ --password= ]] || [[ "$CMD" =~ /password= ]]; then
    echo "PID=$PID USER=$USER CMD=$CMD"
  fi
done

How We Exposed a Password in Production

It turned out that we had a nightly backup running via cron with the command:

sshpass -p 'MySecret123' ssh backup@10.1.1.25

Other users were also working on the server. The password showed up in process monitoring.

On top of that, Jenkins saved this same command in pipeline logs accessible to all project members. We had to urgently rotate keys, clean up tasks, and tighten controls.

Quick Reference of Vulnerable Tools

ToolPassword ParameterWhere It's Exposed
sshpass-pps, /proc
plink / pscp-pwTask Manager
WinSCP CLI/password=cmdline
rsync--password-fileif file is accessible
curl / wgethttp://user:pass@arguments
mysql--password=warning shown
smbclientuser%passps
Jenkinssh "sshpass..."logs

What to Implement in Your Process

Linux — cron scanners, Ansible, shell scripts.

Windows — PowerShell + logging.

CI/CD — linters and scanners (Checkov, KICS, Semgrep).

IDE — pre-commit hooks that forbid commands with passwords in arguments.

Example Semgrep rule:

pattern: sshpass -p $PASS ...
message: 'Password is passed on the command line — this is insecure.'
severity: ERROR

How to Do It Securely

  • Use ssh-agent and keys without passwords in scripts.
  • Store secrets in Vault, AWS Secrets Manager, Ansible Vault.
  • Hide credentials in .pgpass, .my.cnf, .netrc (permissions 600).
  • Segregate access: nobody except root should see other users' processes.
  • Restrict or remove dangerous utilities (sshpass, etc.).
  • When secrets must be stored in files, use encoding.

Conclusion

One innocent optimization could have resulted in a leak. We found and closed the hole, added regular checks, and our colleague switched to keys.

Tip: check your servers right now. If passwords are in arguments — remove them immediately. Such small things can cost far more than five minutes of setup.

P.S. Have you had a similar experience? Share how you found and closed such holes. Perhaps we can compile a useful collection of practices.