I have gpg-agent running with a cached passphrase for an hour or so. I encrypt my email account passwords for offlineimap IMAP sync utility and have the script pass in the passwords by decrypting them from a GPG-encrypted file.

Since I run offlineimap with systemd as it is a cron job, it will naturally pop-up a pinentry program and ask for the password. I was wondering is there a way to programtically confirm if gpg-agent will need a passphrase so I can query for the information, and gracefully exit the systemd/cron job if interactive passphrase input is required.

Has anyone done this before?


I just have the similar plan to periodically fetch/sync may emails using mbsync and cron. The passwords are managed by pass which uses GnuPG to encrypt the sensitive data.

The newer GnuPG (I'm using v2.1.18) must use gpg-agent to ask for the necessary passphrase to decrypt the private keys. And gpg-agent will be automatically started when e.g., I invoke pass to get the password for my email account, and will pop up the pinentry dialog asking the passphrase.

I don't want to configure gpg-agent to cache my passphrase for too long (e.g., 1 day or even 1 year), and I don't want the annoying pinentry dialog from gpg-agent triggered by the cron jobs, which should be just quiet.

I think the mbsync cron job will sync my emails when gpg can just decrypt the password for pass without triggering gpg-agent to ask the user for the passphrase, otherwise, the cron job will just exit.

I found GnuPG has the --pinentry-mode option, which may have values:

  • default : Use the default of the agent, which is ask.
  • ask : Force the use of the Pinentry.
  • cancel : Emulate use of Pinentry's cancel button.
  • error : Return a Pinentry error (``No Pinentry'').
  • loopback : Redirect Pinentry queries to the caller. Note that in contrast to Pinentry the user is not prompted again if he enters a bad password.

Therefore, I can explicitly disable pinentry usage by passing --pinentry-mode cancel or --pinentry-mode error, and let gpg try to sign/decrypt a message. If it succeeded, then gpg-agent already has the cached passphrase and will not pop up the pinentry dialog; otherwise, the sign/decrypt test just failed.

For example:

When gpg-agent doesn't cache the needed passphrase:

$ echo "test" | \
  gpg2 --sign --batch --no-tty --pinentry-mode error \
       --local-user <you@example.com> -o /dev/null

# Return code: 2
# gpg: signing failed: No pinentry
# gpg: signing failed: No pinentry

When gpg-agent has already cached the passphrase, the same command will succeed and return status code 0.

If I use --pinentry-mode cancel, then gpg fails with Operation cancelled.


I don't know for sure, but I wonder if it is sensible to have such an option because it could easily misused like:

if gpg_ready_to_work_without_pinentry; then

and you'd not have any chance to detect a misuse. (In fact I even don't like that every program in my login session has access to my possibly unlocked key without a way to check if it's unlocked or not. I found your question on the search for an option to gpg-agent to pop up a confirmation dialog for each usage exactly for this reason.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.