Configuring File Permissions in OpenSSH SFTP: How to Customize or Disable Default 640 Mode


5 views

When working with OpenSSH's SFTP client on Linux systems, you'll notice it automatically sets file permissions to 640 (rw-r-----) during file transfers, unlike many GUI SFTP clients which don't explicitly set permissions. This behavior stems from OpenSSH's implementation that preserves original file modes by default.


$ sftp user@example.com
Connected to example.com.
sftp> put example.txt
Uploading example.txt to /home/user/example.txt
example.txt                                    100%   12KB   1.2MB/s   00:00

Looking at the OpenSSH source code (src/sftp-client.c), we can see the client attempts to preserve file modes regardless of whether the -P flag is specified:


/*
 * Preserve file modes by default
 */
if (!preserve_flag && (st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != 0) {
    attrib_flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
    attrib.permissions = st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
}

Option 1: Using umask

The most straightforward solution is to set the umask before running sftp:


$ umask 0022  # Results in 644 permissions
$ sftp user@example.com

Option 2: Post-transfer chmod

You can modify permissions after transfer using sftp's chmod command:


sftp> put file.txt
sftp> chmod 755 file.txt

Option 3: Alternative SFTP Clients

As mentioned in the original post, clients like PuTTY's PSFTP don't enforce permissions:


psftp> open user@example.com
psftp> put file.txt

For OpenSSH server administrators, you can modify the sshd_config to influence default permissions:


# /etc/ssh/sshd_config
Subsystem sftp internal-sftp -u 0002  # Sets umask for SFTP connections

For complete control, create a wrapper script that handles permission setting:


#!/bin/bash
# sftp-wrapper.sh
TARGET_PERMS=$1
shift
sftp $@ <

Usage example:


$ find . -type f | ./sftp-wrapper.sh 644 user@example.com

When working with OpenSSH's sftp command, many developers encounter unexpected behavior regarding file permissions. Unlike GUI clients like WinSCP or FileZilla that don't explicitly set modes, the OpenSSH client defaults to applying 640 permissions (rw-r-----) on uploaded files.


# Typical sftp upload with implicit 640 permissions
sftp user@host
put localfile.txt /remote/path/

The behavior stems from OpenSSH's source code where the client attempts to preserve file modes by default, even when the -P flag (preserve permissions) isn't specified. This occurs in the upload.c file where the client sets the mode bits during SSH_FXP_OPEN.

For those needing different permission behavior, consider these approaches:

1. Using umask Adjustments

Configure the server's umask to modify the final permissions:


# In /etc/ssh/sshd_config
Subsystem sftp /usr/lib/openssh/sftp-server -u 0002

2. Post-transfer Permission Modification

Chain commands to modify permissions after upload:


sftp user@host <

3. Alternative Clients

As mentioned in the original post, PuTTY's PSFTP client handles permissions differently. Example usage:


psftp user@host -b upload.txt
# upload.txt contents:
put localfile.txt /remote/path/

For those comfortable with compiling from source, you could modify the upload.c behavior:


// Around line 986 in upload.c (OpenSSH 8.9)
if (!preserve_flag) {
    // Original: attrib_to_set |= SSH2_FILEXFER_ATTR_PERMISSIONS;
    attrib_to_set = 0;  // Skip permission setting
}

Here's a complete bash script example that handles uploads with custom permissions:


#!/bin/bash
SFTP_HOST="example.com"
SFTP_USER="user"
TARGET_DIR="/remote/path"
LOCAL_FILE="data.csv"
REMOTE_PERMS="664"

sftp -b - ${SFTP_USER}@${SFTP_HOST} <