Skip to content

Instantly share code, notes, and snippets.

@jeremy-code
Created March 25, 2025 05:49
Show Gist options
  • Save jeremy-code/79e1f1b58a03ae4c70be49c214eca190 to your computer and use it in GitHub Desktop.
Save jeremy-code/79e1f1b58a03ae4c70be49c214eca190 to your computer and use it in GitHub Desktop.
GnuPG Permissions Configuration

GnuPG Permissions Configuration

TL;DR

If you only care about getting rid of the warning:

# Use root to make the user the owner of the GPG homedir and the GPG config file
sudo chown $USER ~/.gnupg ~/.gnupg/gpg.conf

# Set directory to allow the user to read, write and search (execute)
chmod u=rwx,go= ~/.gnupg # 700 (rwx------)

# Set config file to readable and writable for user.
chmod u=rw,go= ~/.gnupg/gpg.conf # 600 (rw-------)

If you only care about getting rid of the warning and you have a custom base directory ($GNUPGHOME):

sudo chown $USER $GNUPGHOME "$GNUPGHOME/gpg.conf"
chmod u=rwx,go= $GNUPGHOME
chmod u=rw,go= "$GNUPGHOME/gpg.conf"

Otherwise, if you want to set everything in the directory with consistent permissions:

# Use root to make the user the owner of the homedir and its files recursively
sudo chown -R $USER ~/.gnupg

# All files (f) and sockets (s) in ~/.gnupg can only be read and written by the user/owner.
find ~/.gnupg -type fs -exec chmod u=rw,go= {} +

# All directories in ~/.gnupg (including itself) are read, write, and executable
find ~/.gnupg -type d -exec chmod u=rwx,go= {} +

or with a custom base directory ($GNUPGHOME):

sudo chown -R $USER "$GNUPGHOME"
find "$GNUPGHOME" -type fs -exec chmod u=rw,go= {} +
find "$GNUPGHOME" -type d -exec chmod u=rwx,go= {} +

Firstly, sudo may have unexpected behavior with permissions. For example:

~ sudo whoami
root
~ sudo echo "whoami: $(whoami), user: $USER"
whoami: jeremy, user: jeremy
~ gpg --version
gpg (GnuPG) 2.4.7
~ sudo gpg --version
gpg: WARNING: unsafe ownership on homedir '/Users/jeremy/.gnupg'
gpg (GnuPG) 2.4.7

So if you just run sudo chown -R $USER ~/.gnupg (or sudo chown -R $USER $GNUPGHOME if you've set it), you should be good to go. $USER is always avaliable to sudo (some env variables are removed -- run sudo env to see what's avaliable). -R means it's recursive (all files and directories within ~/.gnupg will now be owned by you).

Also, setting the "execute" permission in a directory is to search or show metadata. Also, if write is also set, you can cd or ls in the directory.

In GnuPG, by default, if GnuPG detects unsafe permissions, it will issue a warning. Unfortunately, there isn't much documentation on this behavior besides a brief mention regarding the "--no-permission-warning" option, which disables the warning.

Taking a closer look at the source code (see check_permissions()), the behavior is as follows:

The user invoking gpg (hereafter "user") must have the correct permissions on the following directories and files:

  1. GPG Homedir (~/.gnupg by default, or $GNUPGHOME if set)
  • The owner of the homedir MUST be the user
  • The homedir MUST be a directory
  • The homedir must have permissions such that group is NOT read/write/execute and other is NOT read/write/execute (i.e. x00 in octal, d***------ in symbolic notation)
  1. GPG Config (~/.gnupg/gpg.conf by default or $GNUPGHOME/gpg.conf)
  • The owner of the GPG config file MUST be the user or root
  • The permissions must be such that:
    • If the file is NOT group or other writable, the enclosing directory must ALSO NOT be group or other writable.
    • If the file IS group or other writable, the enclosing directory must NOT be group or other read/write/executable.
  1. Extensions. Same process as the GPG config file

In other words, these are all valid:

sudo chown $USER ~/.gnupg ~/.gnupg/gpg.conf
chmod u=rwx,go= ~/.gnupg
chmod u=rw,go= ~/.gnupg/gpg.conf
sudo chown $USER ~/.gnupg
sudo chown root ~/.gnupg/gpg.conf
chmod u=rwx,go= ~/.gnupg
chmod ugo=rwx ~/.gnupg/gpg.conf

There are two caveats that I am not certain about:

  1. I believe the "enclosing folder" of the GPG config is ALWAYS the GPG homedir

I don't believe you can set the GPG config file to be in a different directory, but I could be wrong. I am not sure how you would set a different enclosing folder.

I suspect this code is intended to allow for checking the permissions of extensions. If this is the case, then the only condition that matters is that the owner of the GPG config file is that the owner is user or root.

  1. I don't believe the check_permissions() function is used for extensions

From what I can tell, in that gpg.c, check_permissions() is only used in two places, one to check the GPG homedir (#2637) and again to check the (non-global) GPG config file (#2671). Based on what I can tell, it isn't used for dirmngr.conf or gpg-agent.conf. A quick check on Github (/check_permissions\(.*, 2\)/ language:C) also doesn't show any results. This may change in the future.

So for a quick fix, you can run:

# Use root to make the user the owner of the GPG homedir and the GPG config file
sudo chown $USER ~/.gnupg ~/.gnupg/gpg.conf

# Set directory to allow the user to read, write and search (execute)
chmod u=rwx,go= ~/.gnupg # 700 (rwx------)

# Set config file to readable and writable for user.
chmod u=rw,go= ~/.gnupg/gpg.conf # 600 (rw-------)

# OR Custom base dir ($GNUPGHOME)
sudo chown $USER $GNUPGHOME "$GNUPGHOME/gpg.conf"
chmod u=rwx,go= $GNUPGHOME
chmod u=rw,go= "$GNUPGHOME/gpg.conf"

However, if you're going to be changing permissions in ~/.gnupg, you probably should go all the way and set permissions for everything. In that case, you can do:

# Use root to make the user the owner of the homedir and its files recursively
sudo chown -R $USER ~/.gnupg

# All files (f) and sockets (s) in ~/.gnupg can only be read and written by the user/owner.
find ~/.gnupg -type fs -exec chmod u=rw,go= {} +

# All directories in ~/.gnupg (including itself) are read, write, and executable
find ~/.gnupg -type d -exec chmod u=rwx,go= {} +

# OR Custom base dir ($GNUPGHOME)
sudo chown -R $USER "$GNUPGHOME"
find "$GNUPGHOME" -type fs -exec chmod u=rw,go= {} +
find "$GNUPGHOME" -type d -exec chmod u=rwx,go= {} +
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment