It depends on whether the shell you're using has echo
as a builtin, or uses an external binary (/bin/echo). If it's an external binary, it'll be run as a subprocess with the password plainly visible in its argument list (via ps
, pgrep
, etc). If it's a builtin, an echo
command in a pipeline will run as a subprocess, but it'll be a subshell with the same visible argument list as the parent shell (i.e. it's safe).
So it's probably safe, but there are several complications to worry about. First, if you're running this on a remote computer via ssh
, you don't necessarily know what its default shell is. If it's bash, you're ok. If it's dash, I think you have a problem. Second, you don't just have to worry about the remote shell and/or echo
command, you have to worry about every step along the path from your local script to that remote echo
command. For example, if you use:
ssh user@computer "echo -e 'old\nnew\nnew' | passwd"
...then the remote echo
is probably safe (depending on the remote shell), but as @thatotherguy pointed out the password will be visible in both the remote shell's (bash -c echo -e 'foo\nbar\nbar' | passwd
) and in the local ssh
process's argument list.
There's another complication, BTW: echo
isn't consistent about how it handles options (like -e
) and escapes in the output string (see this question for an example). You're much better off using printf
(e.g. printf '%s\n' "$oldpass" "$newpass" "$newpass"
), which is also a builtin in bash. Or, if you're sure you're using bash, you can use here-string (<<<string
) instead. It doesn't interpret escapes at all, but you can use bash's $' '
construct to interpret them:
passwd <<<"$old"$'\n'"$new"$'\n'"$new"
This doesn't involve a subprocess at all (either /bin/echo
or a subshell), so no worries about the process table.
Another possibility to avoid both the problems of uncertain remote shells and the password showing up in ssh
's argument list is to pass the passwords via ssh
's stdin:
ssh user@computer passwd <<<"$old"$'\n'"$new"$'\n'"$new"