Back to blog

Git: Time To Switch to HTTPS?

10/25/2022

Jakob Gillich

GitHub finally introduced granular access tokens that let you limit access to select repositories. Personal access tokens can authorize Git with HTTPS.

Like many, I use Git with SSH on my desktop. SSH keys grant access to all repositories, whereas access tokens can be much more limited. This is great for servers and automation use-cases, but should you also prefer access tokens, and therefore HTTPS for your personal machines?

HTTPS is more secure (usually)#

Connecting to a Git server over SSH for the first time presents you with this message:

$ git clone git@github.com:example/example
The authenticity of host 'github.com (IP ADDRESS)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)?

When you see this, do you:

  1. Compare the fingerprint to the one published by GitHub, and if it matches, type yes
  2. Just type yes

If your answer is 2, you are vulnerable to a man-in-the-middle attack. This is not a problem with HTTPS because certificate authorities like Let's Encrypt verify the ownership of a domain.

You authenticate with HTTPS by sending a plain-text to the server, whereas SSH uses public-key crypto. Sending a token to a trusted server over a encrypted connection is fine, but the best way to never expose a secret is to never send it over the wire. You can also embed SSH tokens in a hardware device like the YubiKey for extra-secure storage.

If used right, SSH is more secure. But for the 99% (?) of us who don't verify fingerprints, HTTPS wins. HTTPS also enables the use of granular tokens.

SSH is more convenient#

Your SSH keys are stored in the ~/.ssh directory and automatically used by Git to authenticate. Git provides credential helpers for use with HTTPS. The cache helper stores credentials in memory temporarily. The store helper stores them in plain text on disk, which you may not want to do. You could use a .netrc file in your home directory:

machine github.com
  login example
  password github_token

This will work out of the box, and with git-credential-netrc you could encrypt this file using gpg.

Alternatively, you could use the credential store built into your operating system, which will typically encrypt your secrets using your login password.

Linux/GNOME

# On Fedora, for others see below
sudo dnf install git-credential-libsecret

git config --global credential.helper libsecret

OSX

git config --global credential.helper osxkeychain

Windows

git config --global credential.helper wincred

Once configured, Git will automatically store your credentials in the OS secret store.

See this StackOverflow question for more information.

This approach does have one problem: Containerized environments will not be able to access your local secret store unless they specifically support it. As a heavy user of VSCode Remote Containers, it's not for me.

SSH authentication just works, whereas HTTPS requires some time to set up if you want to store your credentials in encrypted form. I'd say SSH has the edge in terms of convenience.

HTTPS is easier to host#

SSH is a protocol for remotely controlling machines. It is installed on nearly every Linux server on the internet. When you set up a Git server with SSH, you need to either rebind the default port 22 to our Git server, or you need to move the Git server to another port. It's harder to remember an address like example.com:7392/user/repo, but there is only one port 22.

When hosting multiple Git servers, you have two choices: Use alternative ports or use dedicated IP addresses for each. IPv4 addresses are in short supply, so neither are great options.

HTTPS uses Server Name Indication to tell which server a client is connecting to. You almost never need to use non-default ports when accessing websites. At Cloudplane, we provide managed Gitea instances, and we've chosen to ship with HTTPS support only. Providing SSH ports would be challenging for us.

Bottom line#

SSH remains the most convenient solution for users, but it is vulnerable to attacks unless used correctly. HTTPS is secure and easy to host, but setting up credentials is a little more involved.

Should you switch from SSH to HTTPS? I think SSH is perfectly fine and there is no immediate need to switch. But there are good reasons to prefer HTTPS in some situations, especially now that GitHub supports granular access tokens.