Any idea why sftp is unable to read the temporary file descriptor?
Few facts:
- the
<(pass foo) process substitution will cause bash to create a pipe, run the pass foo command asynchronously with its output connected to the writing end of the pipe and replace the <(...) with a path of the form /dev/fd/63, where 63 is the file descriptor referring to the reading end of the pipe.
- the
/dev/fd/63 is a special path which allows a process to stat() and re-open the file referred by one of its file descriptors.
- the shell forks + execs
sftp, then sftp itself forks and execs ssh, causing the 63 file descriptor to be passed down via inheritance.
ssh will close all its file descriptors except 0, 1, 2 using the closefrom() function. That will also close fd 63.
Since 63 is no longer an open file descriptor in the ssh process, a stat() on /dev/fd/63 will fail with the error from the OP.
How to fix it?
Temporarily store the key in a filesystem in memory. In my Debian systemd provides me tmpfs under /run/user/<myUID>. The mountpoint is inaccessible to anyone but me (and root, of course).
Note a rogue process running under your user (or root) can read the file. But such process could also read from sshd's file descriptor 63 in your original approach.
Alternatively, when there is no safe tmpfs available:
Create a temporary fifo. Note mktemp cannot do this directly. The safe way is to create a temporary private directory and then mkfifo in it.
Make sure the permissions of the fifo itself are narrow, otherwise ssh will complain.
Run
sftp -i "/temp_dir/the_fifo" user@host
In parallel run pass foo > "/temp_dir/the_fifo". A quirk: you need to do this twice; at least in my Debian ssh reads the key twice. The following command seems to work in my tests: cat ~/.ssh/id_rsa > "/temp_dir/the_fifo" && cat ~/.ssh/id_rsa > "/temp_dir/the_fifo". Probably a similar duplicated command will work for you:
pass foo > "/temp_dir/the_fifo" && pass foo > "/temp_dir/the_fifo"
You can run it in the background just before sftp (unless pass is interactive, I'm not familiar with the tool at all).
At the end remove the fifo and the directory.
Still, a rogue process running under your user (or root) can read from the fifo before ssh does.