Post

Secure SMTP Authentication for Git and b4 Using GPG-Encrypted netrc

Secure SMTP Authentication for Git and b4 Using GPG-Encrypted netrc

Email-driven patch workflows remain the gold standard across major open-source projects, including the Linux kernel, U-Boot, Buildroot, and QEMU. Tools like git send-email and b4 make preparing, signing, and sending patch series seamless.

However, when submitting patches outside of the Linux kernel mailing list (LKML) infrastructure, or when your email provider enforces Two-Factor Authentication (2FA), managing SMTP credentials securely becomes a critical step.

In this guide, we will explore how to securely store and use SMTP App Passwords using GPG-encrypted .netrc files integrated directly with Git and b4.


The Problem: Web Submission Limits & Plaintext Credentials

1. Kernel.org Web Submission Endpoint Limitations

b4 comes configured by default to submit patches through the public web endpoint (https://lkml.kernel.org/_b4_submit). While this is ideal for kernel subsystem trees, the endpoint strictly verifies destination mailing lists.

If you attempt to submit a patch series to other projects (e.g., buildroot@buildroot.org), the submission will fail:

1
2
3
Reflecting via web endpoint https://lkml.kernel.org/_b4_submit
Error from endpoint: Destinations must include a mailing list we recognize.
CRITICAL: Was not able to send messages.

For non-kernel projects, you must route your patches through your own mail server via SMTP.

2. The 2FA and Plaintext Dilemma

Modern email providers (Google Workspace, Fastmail, Proton, iCloud, etc.) require App-Specific Passwords for SMTP when 2FA is active.

A common pitfall is storing this App Password directly in plaintext inside ~/.gitconfig:

1
2
3
4
[sendemail]
    smtpserver = smtp.example.com
    smtpuser = user@example.com
    smtppass = "secret-app-password" # Insecure plaintext!

If your dotfiles are version-controlled, public, or backed up unencrypted, your SMTP credentials are exposed.


The Solution: GPG-Encrypted ~/.netrc.gpg

Git includes a modular credential helper system. One of its most powerful helpers is git-credential-netrc.

The netrc helper:

  1. Reads credentials from standard netrc files.
  2. Automatically detects .gpg encrypted files.
  3. Invokes gpg to decrypt credentials only in memory when requested by Git or b4.
  4. Leverages gpg-agent to cache decryption keys in RAM for your session—avoiding repetitive password prompts.

Step 1: Install the git-credential-netrc Helper

On Debian/Ubuntu-based distributions, Git includes git-credential-netrc as a contrib Perl script, but it is not linked in $PATH by default.

Ensure ~/.local/bin exists and is in your $PATH, then copy and make the script executable:

1
2
3
4
5
6
mkdir -p "$HOME/.local/bin"

if [ -f /usr/share/doc/git/contrib/credential/netrc/git-credential-netrc.perl ]; then
    cp -f /usr/share/doc/git/contrib/credential/netrc/git-credential-netrc.perl "$HOME/.local/bin/git-credential-netrc"
    chmod +x "$HOME/.local/bin/git-credential-netrc"
fi

Verify that Git can find the helper:

1
git-credential-netrc --help

Step 2: Create and Encrypt ~/.netrc.gpg

  1. Create a temporary plaintext file containing your SMTP host, username, and generated App Password:
1
2
3
4
5
6
cat << 'EOF' > /tmp/netrc_plain
machine smtp.your-provider.com
login user@example.com
password your-generated-app-password
port 587
EOF

Note: Replace smtp.your-provider.com with your provider’s SMTP server (e.g., smtp.gmail.com, smtp.fastmail.com, etc.).

  1. Encrypt the file using your GPG key, then remove the plaintext file:
1
2
3
gpg -e -r user@example.com -o ~/.netrc.gpg /tmp/netrc_plain
rm -f /tmp/netrc_plain
chmod 600 ~/.netrc.gpg

Your credentials are now protected at rest with your GPG private key.


Step 3: Configure Git and b4

Configure Git’s credential.helper and SMTP settings:

1
2
3
4
5
6
7
8
# 1. Register the netrc credential helper pointing to your encrypted file
git config --global credential.helper "netrc -f ~/.netrc.gpg"

# 2. Configure standard SMTP parameters (leave smtppass empty)
git config --global sendemail.smtpserver smtp.your-provider.com
git config --global sendemail.smtpuser user@example.com
git config --global sendemail.smtpencryption tls
git config --global sendemail.smtpserverport 587

How It Works Under the Hood

When you execute b4 send or git send-email:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[b4 / git send-email]
         │
         ▼ (Requests password for smtp.your-provider.com)
[git credential fill]
         │
         ▼ (Runs: git-credential-netrc -f ~/.netrc.gpg get)
[git-credential-netrc]
         │
         ▼ (Detects .gpg extension -> calls gpg --decrypt)
[gpg-agent / pinentry] ──> [Decrypted in memory]
         │
         ▼ (Matches machine & login)
[Returns password to b4 / git]
         │
         ▼
[Authenticates via TLS & Sends Patches]
  1. b4 checks your Git configuration and sees smtpuser is set, but smtppass is omitted.
  2. It invokes git credential fill with protocol=smtp, host=smtp.your-provider.com:587, and username=user@example.com.
  3. Git executes git-credential-netrc -f ~/.netrc.gpg get.
  4. The helper sees the .gpg extension and runs gpg --decrypt ~/.netrc.gpg.
  5. gpg-agent prompts for your master passphrase/hardware token (or uses its active session cache) and decrypts the stream directly into RAM.
  6. The matching password token is passed back to b4, which authenticates and sends your email over TLS.

Step 4: Test Your Configuration

You can safely test your setup by using b4 send --reflect (which populates all headers as intended, but delivers the series strictly to your own email address):

1
b4 send --reflect

You should see b4 connect to your configured SMTP server, authenticate seamlessly via the credential helper, and deliver the reflection to your inbox.


Summary

With git-credential-netrc and GPG:

  • Zero Plaintext: Passwords remain encrypted on disk with strong public-key cryptography.
  • Hardware Token Compatible: Supports YubiKeys and smartcards configured with GPG subkeys.
  • Seamless Integration: Both git send-email and b4 query Git’s native credential subsystem without requiring wrapper scripts or third-party daemon configuration.
This post is licensed under CC BY 4.0 by the author.