Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:
Sending a Password via SSH or SCP Using subprocess.Popen in Linux
Last updated: May 6, 2025
1. Overview
Secure Shell (SSH) and Secure Copy Protocol (SCP) are commonly used tools for secure remote access and file transfer in Linux environments. Automating these tasks using Python’s subprocess.Popen can be helpful in scenarios where password authentication is required.
In this tutorial, we’ll learn how to securely send a password using subprocess.Popen while avoiding common security pitfalls.
2. Understanding subprocess.Popen
The subprocess module in Python enables us to spawn new processes, connect to their input, output, and error pipes, and obtain their return codes. The Popen class is particularly useful for interacting with processes programmatically.
Here’s a basic example to run an SSH command using subprocess.Popen:
import subprocess
process = subprocess.Popen([
'ssh', 'user@remote_host', 'ls'
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print(stdout.decode())
This approach works well when using SSH keys for authentication. If password authentication is needed, subprocess.Popen doesn’t support sending it securely by default.
3. Why Sending Passwords Directly Is Risky
Passing passwords via standard input or command-line arguments introduces several risks:
- Passwords may appear in the shell history
- Passwords could be exposed through process listing (e.g., ps aux)
- Automation scripts might inadvertently log them
Tools such as sshpass or pexpect help reduce these risks effectively.
4. Using sshpass With subprocess.Popen
sshpass is a utility that allows non-interactive SSH authentication by passing a password via a command-line argument or standard input.
4.1. Installing sshpass
Let’s install sshpass using the system’s package manager:
$ sudo apt install sshpass # Debian-based systems
$ sudo yum install sshpass # RHEL-based systems
Once installed, we can use it to invoke SSH commands.
4.2. Using sshpass With subprocess.Popen
Let’s use sshpass to run an SSH command from Python:
import subprocess
password = "your_password"
command = [
'sshpass', '-p', password, 'ssh', 'user@remote_host', 'ls'
]
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print(stdout.decode())
Although the code works, there are security concerns to be aware of.
4.3. Security Considerations
While sshpass helps with automation, there are notable concerns:
- sshpass exposes the password in the process list
- Logs and history may retain the password
- Employing sshpass isn’t recommended for production use
These concerns make sshpass less ideal for secure environments. Let’s look at a more secure alternative.
5. Using pexpect for Secure Password Handling
pexpect simulates user interaction, allowing secure password entry and improved automation handling.
5.1. Installing pexpect
Let’s install pexpect using pip:
$ pip install pexpect
With pexpect ready, let’s automate SSH connections more securely.
5.2. Using pexpect for SSH
The following example demonstrates how to automate SSH login using pexpect:
import pexpect
user = "user"
host = "remote_host"
password = "your_password"
command = "ls"
ssh_command = f"ssh {user}@{host} {command}"
child = pexpect.spawn(ssh_command)
child.expect("password:")
child.sendline(password)
child.expect(pexpect.EOF)
print(child.before.decode())
Let’s extend the same approach to handle file transfers.
5.3. Using pexpect for SCP
We can automate SCP transfers securely using pexpect:
import pexpect
user = "user"
host = "remote_host"
password = "your_password"
local_file = "file.txt"
remote_path = "/home/user/file.txt"
scp_command = f"scp {local_file} {user}@{host}:{remote_path}"
child = pexpect.spawn(scp_command)
child.expect("password:")
child.sendline(password)
child.expect(pexpect.EOF)
print(child.before.decode())
Aside from convenience, pexpect improves the overall security posture.
5.4. Security Benefits
Using pexpect offers several security benefits:
- The password doesn’t appear in the command history or process list
- Better interaction control for automation
- More secure than sshpass
These advantages make pexpect a preferable option for password-based automation.
6. Best Practices for Secure SSH Automation
Although password authentication can be automated, it’s usually better to use SSH keys for stronger security. Let’s walk through setting up SSH key authentication.
6.1. Generating SSH Keys
To create a new key pair, let’s use the ssh-keygen command:
$ ssh-keygen -t rsa -b 4096
Once the keys are generated, we place the public key on the remote system.
6.2. Copying the Public Key to the Remote Host
Let’s copy the public key to the remote host:
$ ssh-copy-id user@remote_host
Now, we can use key-based authentication in our Python script.
6.3. Using SSH Keys in Python
Once the SSH key is in place, let’s use it in Python:
import subprocess
process = subprocess.Popen([
'ssh', '-i', '/path/to/private_key', 'user@remote_host', 'ls'
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print(stdout.decode())
SSH keys provide a more secure and efficient way to automate authentication in Python.
7. Conclusion
In this article, we saw how automating SSH and SCP operations using subprocess.Popen is possible but involves security challenges when passwords are required. Tools like pexpect offer a safer alternative to sshpass. However, using SSH keys remains the most secure and efficient method. By following these best practices, we can build robust and secure automation workflows.