Notice: the very same vulnerability has been discussed in this question, but the different setting of the problem (in my case I don't need to store the passphrase) allows for a different solution (i.e. using file descriptors instead of saving the passphrase in a file, see ilkkachu's answer).

Suppose I have a symmetrically encrypted file my_file (with gpg 1.x), in which I store some confidential data, and I want to edit it using the following script:

read -e -s -p "Enter passphrase: " my_passphrase
gpg --passphrase $my_passphrase --decrypt $my_file | stream_editing_command | gpg --yes --output $my_file --passphrase $my_passphrase --symmetric
unset my_passphrase

Where stream_editing_command substitutes/appends something to the stream.

My question: is this safe? Will the variable $my_passphrase and/or the decrypted output be visible/accessible in some way? If it isn't safe, how should I modify the script?

  • 2
    see also unix.stackexchange.com/q/400772/30851 Commented Sep 17, 2018 at 10:17
  • 3
    In addition to passphrase leaking to the process list, your command chain might overwrite the file before you had a chance to decrypt it, resulting in data loss. Commented Sep 17, 2018 at 10:22
  • 4
    Regarding the "disclaimer" that you added. It is the same issue. You store the passphrase in a variable and use it on the command line when calling gpg. It will therefore be visible in the output of ps. It is not possible to call a program with a password on the command line securely. This is why gpg and other programs that takes passwords often read them from a file. A file can be made read protected for anyone but the file's owner (and root).
    – Kusalananda
    Commented Sep 17, 2018 at 19:42
  • 1
    There is a slight difference between this and the linked question: That one asks about running gpg through cron, which pretty much forces using some sort of persistent storage for the passphrase (i.e. a file).
    – ilkkachu
    Commented Sep 17, 2018 at 20:24

1 Answer 1

gpg --passphrase $my_passphrase 

My question: is this safe? Will the variable $my_passphrase and/or the decrypted output be visible/accessible in some way?

No, that's not really considered safe. The passphrase will be visible in the output of ps, just like all other running processes' command lines. The data itself will not be visible, the pipe is not accessible to other users.

The man page for gpg has this to say about --passphrase:

--passphrase string    

Use string as the passphrase. This can only be used if only one passphrase is supplied. Obviously, this is of very questionable security on a multi-user system. Don't use this option if you can avoid it.

Of course, if you have no other users on the system and trust none of your services have been compromised there should be no-one looking at the process list.

But in any case, you could instead use --passphrase-fd and have the shell redirect the passphrase to the program. Using here-strings:

read -e -s -p "Enter passphrase: " my_passphrase
echo        # 'read -s' doesn't print a newline, so do it here
gpg --passphrase-fd 3 3<<< "$my_passphrase" --decrypt "$my_file" |
    stream_editing_command |
    gpg --yes --output "$my_file" --passphrase-fd 3 3<<< "$my_passphrase" --symmetric

Note that that only works if the second gpg doesn't truncate the output file before getting the full input. Otherwise the first gpg might not get to read the file before it's truncated.

To avoid using the command line, you could also store the passphrase in a file, and then use --passphrase-file. But you'd then need to be careful about setting up the access permissions of the file, to remove it afterwards, and to choose a proper location for it so that the passphrase doesn't get actually stored on persistent storage.

  • I assume that the output-being-truncated issue is avoided if another file is used for the output of the second gpg command (i.e. gpg --yes --output "$another_file"), am I right? Commented Sep 19, 2018 at 8:10
  • 1
    @francescop21, yep. Or pipe the result through sponge.
    – ilkkachu
    Commented Sep 19, 2018 at 9:12
  • @ilkkachu In gpg --passphrase-fd 3 3<<< "$my_passphrase" --decrypt "$my_file", is my_passphrase stored as environment variable for the script? Is it safe to store it like that? It would be available in the bash history and also while (or after) assigning the variable, would it be available to other processes?
    – Porcupine
    Commented Jun 30, 2021 at 2:05
  • @Porcupine, my_passphrase would be a shell variable, in the memory of the shell (plus where ever it was read from). It would get exported in the environment of other processes only if you run export my_passphrase in the script. It's not that easy to read the memory of a process, or the environment variables. Stuff on the command line is a different thing, since by default on Linux, the command line of a process can be read by any user on the system (via /proc, and with stuff like ps).
    – ilkkachu
    Commented Jun 30, 2021 at 8:45
  • @ilkkachu Forgive me, for I am a noob. If your above script is called as A.sh. Do you execute it like my_passphrase="xxxxxxxx" bash A.sh? Is this secure? (PS: How else can we run your script?)
    – Porcupine
    Commented Jun 30, 2021 at 10:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .