Bash

How to run the sftp command with a password from Bash script

19 September 2026 · 10 min read

How to run the sftp command with a password from Bash script

Running the sftp command with a password from a Bash script presents a common challenge for system administrators and developers automating file transfers. While interactive sftp sessions are straightforward, automating them within scripts requires careful consideration of security and best practices. Directly embedding passwords in scripts is generally discouraged due to security risks. However, certain scenarios may necessitate this approach, especially in controlled environments or during initial setup phases. This article explores secure and practical methods for automating sftp with passwords in Bash scripts, focusing on alternatives to hardcoding credentials and providing safer solutions for your automation needs. We’ll cover techniques like using expect scripts, leveraging SSH keys, and employing password managers to handle sensitive information securely. Understanding these methods allows you to streamline your file transfer processes while minimizing security vulnerabilities.

Understanding the Risks of Hardcoding Passwords

Directly embedding passwords within a Bash script, while seemingly convenient, introduces significant security vulnerabilities. If the script is compromised, the password becomes immediately accessible, potentially granting unauthorized access to sensitive data. Consider a scenario where a script containing a hardcoded password is accidentally committed to a public repository. Anyone with access to the repository can then retrieve the password and potentially compromise the server. This is a major security breach that can have severe consequences. According to Verizon’s 2023 Data Breach Investigations Report, weak or stolen credentials remain a primary attack vector for cybercriminals [ Verizon DBIR ].

Furthermore, hardcoded passwords violate the principle of least privilege, which dictates that users and processes should only have the minimum level of access necessary to perform their tasks. By embedding a password in a script, you are potentially granting broader access than intended. Password rotation also becomes problematic with hardcoded credentials. Changing the password requires modifying the script, which can be error-prone and time-consuming. Therefore, it’s crucial to explore alternative methods that prioritize security and maintainability. One way to mitigate the risks of exposing credentials is to store them in environment variables. However, even environment variables can be exposed if not properly secured.

Another critical aspect to consider is compliance. Many security standards, such as PCI DSS and HIPAA, prohibit storing passwords in plain text. Hardcoding passwords in scripts directly violates these standards, potentially leading to penalties and legal ramifications. In summary, while hardcoding passwords might seem like a quick solution, the associated risks far outweigh the convenience. Adopting more secure methods is essential for protecting your systems and data.

Using Expect Scripts for Automated SFTP

Expect is a powerful scripting language designed for automating interactive applications, including sftp. It works by “expecting” certain patterns in the application’s output and then “sending” appropriate responses. This allows you to automate the entire sftp process, including password authentication. To use Expect with sftp, you’ll need to install the Expect package on your system. On Debian-based systems, you can install it using: sudo apt-get install expect. On Red Hat-based systems, you can use: sudo yum install expect. Once installed, you can create an Expect script to handle the sftp interaction.

Here’s an example of an Expect script that automates sftp login and file transfer:

 !/usr/bin/expect -f set timeout 30 set host "your_sftp_host" set username "your_username" set password "your_password" set remotefile "path/to/remote/file" set localfile "path/to/local/file" spawn sftp $username@$host expect "password:" send "$password\r" expect "sftp>" send "get $remotefile $localfile\r" expect "sftp>" send "bye\r" expect eof 

Replace your_sftp_host, your_username, your_password, path/to/remote/file, and path/to/local/file with your actual values. Save this script with a .exp extension (e.g., sftp_transfer.exp) and make it executable using chmod +x sftp_transfer.exp. Now you can run the script using ./sftp_transfer.exp. This script spawns an sftp process, expects the “password:” prompt, sends the password, executes the get command, and then exits the sftp session. While this automates the process, it still embeds the password in the script, which is a security risk. Consider encrypting the script or storing the password in a more secure location. To enhance security, consider prompting the user for the password instead of hardcoding it. You can use the read command with the -s option (for silent input) to achieve this. Here’s an example:

 !/usr/bin/expect -f set timeout 30 set host "your_sftp_host" set username "your_username" puts "Enter password:" stty -echo gets stdin password stty echo set remotefile "path/to/remote/file" set localfile "path/to/local/file" spawn sftp $username@$host expect "password:" send "$password\r" expect "sftp>" send "get $remotefile $localfile\r" expect "sftp>" send "bye\r" expect eof 

This version prompts the user for the password at runtime, preventing it from being stored in the script. This is a more secure approach, but it still requires user interaction. Expect scripts can be complex to debug, so thorough testing is crucial. [ NIST guidance on secure scripting ] recommends rigorous testing and validation of all scripts to prevent unexpected behavior. Leveraging SSH Keys for Passwordless SFTP

A more secure and recommended approach is to use SSH keys for authentication instead of passwords. SSH keys provide passwordless access to the sftp server, eliminating the need to store or transmit passwords. This method relies on public-key cryptography, where a private key is stored on the client machine and a corresponding public key is stored on the server. When connecting to the server, the client uses its private key to prove its identity, without ever sending the password. This is generally the best practice for automating SFTP transfers. The ssh-keygen command generates SSH key pairs.

Here’s how to set up SSH key-based authentication:

  1. Generate an SSH key pair: On your client machine, run ssh-keygen -t rsa -b 4096. You’ll be prompted to enter a file in which to save the key (the default is ~/.ssh/id_rsa) and a passphrase. It’s recommended to use a passphrase for added security, but you can leave it blank for passwordless access.
  2. Copy the public key to the server: Use the ssh-copy-id command to copy the public key to the server: ssh-copy-id username@your_sftp_host. You’ll be prompted for the server password to initially authenticate. This command appends the public key to the ~/.ssh/authorized_keys file on the server.
  3. Test the connection: Try connecting to the server using ssh username@your_sftp_host. If you set up the keys correctly, you should be able to connect without being prompted for a password.

Once SSH key-based authentication is set up, you can use sftp in your Bash script without providing a password. For example: sftp username@your_sftp_host <<< $'get /path/to/remote/file /path/to/local/file\nbye'. This command uses a “here string” to send the sftp commands to the server. Make sure the permissions on your ~/.ssh directory and its contents are restrictive (chmod 700 ~/.ssh and chmod 600 ~/.ssh/) to prevent unauthorized access to your private key. To further enhance security, consider using a dedicated SSH key for your automated scripts. This allows you to revoke the key if the script is compromised, without affecting your other SSH connections. You can also restrict the key’s permissions on the server by using the restrict option in the authorized_keys file. This option limits the commands that can be executed using the key. Here are some of the benefits of using SSH keys:

  • Increased security compared to password-based authentication.
  • Passwordless access, simplifying automation.
  • Granular control over key permissions.

Securely Managing Passwords with Password Managers

Password managers provide a secure way to store and retrieve passwords, eliminating the need to hardcode them in your scripts. Several password managers offer command-line interfaces (CLIs) that can be used to access passwords programmatically. Examples include pass, keepassxc-cli, and Bitwarden CLI. To use a password manager in your Bash script, you’ll first need to install and configure the CLI. For example, to install the Bitwarden CLI, you can use: npm install -g @bitwarden/cli.

Once the CLI is installed, you can use it to retrieve the password from your password manager. For example, if you have a Bitwarden entry named “sftp_password”, you can retrieve the password using: password=$(bw get password sftp_password). This command retrieves the password from Bitwarden and stores it in the password variable. You can then use this variable in your sftp command. Here’s an example:

 !/bin/bash host="your_sftp_host" username="your_username" password=$(bw get password sftp_password) remotefile="path/to/remote/file" localfile="path/to/local/file" sftp "$username":"$password"@"$host" <<< $'get "$remotefile" "$localfile"\nbye' 

This script retrieves the password from Bitwarden and uses it to connect to the sftp server. Note that this method still exposes the password in the command line process list, which is a potential security risk. To mitigate this, consider using process substitution or other techniques to prevent the password from being visible in the process list. Alternatively, you can utilize sftp’s batch mode combined with a password file for a slightly less exposed approach. Create a file (e.g., sftp_commands.txt) containing the necessary sftp commands:

 get /path/to/remote/file /path/to/local/file bye 

Then, use the following command: sftp -o "password=$password" -b sftp_commands.txt $username@$host. This passes the password directly to sftp as a command-line option. While this is still not ideal, it keeps the password out of the main script body. Remember to secure the password manager itself with a strong master password and enable two-factor authentication for added security. Password managers offer a significantly more secure way to handle passwords compared to hardcoding or storing them in plain text. They also provide features like password generation and automatic password updates, further enhancing your security posture. [ OWASP guidelines ] highlight the importance of secure password management in preventing data breaches.
Infographic here
FAQ: Automating SFTP with Passwords in Bash Scripts

Is it safe to hardcode passwords in Bash scripts for SFTP automation?
No, hardcoding passwords in Bash scripts is highly discouraged due to security risks. If the script is compromised, the password becomes immediately accessible, potentially granting unauthorized access to sensitive data.
What are the alternatives to hardcoding passwords for SFTP automation?
Alternatives include using Expect scripts, leveraging SSH keys, and employing password managers. SSH keys are the most secure and recommended approach.
How do SSH keys provide passwordless SFTP access?
SSH keys use public-key cryptography. A private key is stored on the client machine, and a corresponding public key is stored on the server. The client uses its private key to prove its identity without sending the password.
Can I use environment variables to store passwords securely?
While environment variables are better than hardcoding, they can still be exposed if not properly secured. Consider using a password manager for storing sensitive credentials.
What is the recommended approach for automating SFTP transfers securely?
The most secure and recommended approach is to use SSH **Question & Answer :** I need to transfer a log file to a remote host using [sftp](http://en.wikipedia.org/wiki/Secure_file_transfer_program) from a Linux host. I have been provided credentials for the same from my operations group. However, since I don't have control over other host, I cannot generate and share RSA keys with the other host.

So is there a way to run the sftp command (with the username/password provided) from inside the Bash script through a cron job?

I found a similar Stack Overflow question, Specify password to sftp in a Bash script, but there was no satisfactory answer to my problem.

You have a few options other than using public key authentication:

  1. Use keychain
  2. Use sshpass (less secured but probably that meets your requirement)
  3. Use expect (least secured and more coding needed)

If you decide to give sshpass a chance here is a working script snippet to do so:

export SSHPASS=your-password-here sshpass -e sftp -oBatchMode=no -b - sftp-user@remote-host << ! cd incoming put your-log-file.log bye ! 

Update: However do understand that using environment variables is also insecure as using command line option -p for passing password.

It is better to store and read password from a file like this using -f option:

echo 'your-password-here' > ~/.passwd chmod 0400 ~/.passwd sshpass -f ~/.passwd -e sftp -oBatchMode=no -b - sftp-user@remote-host << ! cd incoming put your-log-file.log bye !