Why is SSH safer than HTTPS on direct connections to a Git Repository with Credentials

Solution 1:

It's not clear to me if you were told that SSH is more secure than HTTPS in your particular case (where we don't have all the details), which may be absolutely correct, or whether you've been given this as general advice. The analysis of SSH vs. HTTPS can be surprisingly complex for those not well versed in security systems analysis, which is why we tend to make broad statements such as "SSH is safer than HTTPS": it's generally going to be true, even if it's not true in every case. At any rate, here are some thoughts on the matter.

Since you mention storing credentials in a file, this answer assumes that you're using public/private key authentication for both HTTPS and SSH. Password authentication is significantly less secure in both cases.

Local Credential Store

First, you're working with the assumption that the user's credential stored on disk is not protected by a passphrase. This may or may not be true, but if it were protected by a passphrase this would greatly increase security.

In the case of SSH, the credential is more likely to be protected by a passphrase because key agents are easier to use and more frequently used with SSH. With SSH a key agent is almost invariably available because ssh-agent or similar is part of almost every standard set of SSH client tools. This also makes training to use the agent easy, since training for the use of one tool in one particular way works virtually everywhere.

Key agents for HTTPS systems are far more diverse, probably less commonly installed and, even if available in a particular system, it's less likely that someone would know that a particular one is available and know how to use it.

Remote Agents

Second, SSH supports remote agent connections, allowing one to remove the key material from the system on which you're doing the git fetch which in many cases can lead to vastly improved security. This is best described by an example of my most common workflow.

My laptop is a "personal" machine in the sense that I'm the only one that has access to it. (It has full disk encryption and user accounts only for me.) When I log in, I start a local ssh-agent and load my key (also passphrase-protected) into that, with ssh-askpass confirmation enabled via ssh-add -c.

When I SSH into the host on which I'm doing development, often shared with others, I use ssh -A to enable agent forwarding. I then git fetch, which starts an SSH session from the development host to the server for the Git remote.

That SSH, when requested by the remote to authenticate, receives the request and forwards it back to the agent on my laptop. I receive an alert on my screen that my local agent has received a request to authenticate, which I expect because I have just initiated an action that would cause that, and so I approve the authentication. The SSH process on the development host receives back the information it needs to authenticate (valid for that particular session only), successfully authenticates with the remote server, and my git fetch proceeds.

Note that this is considerably more secure because a) the key was never on the development server and thus much, much less accessible to attackers (they'd need to get to my private laptop), and b) I get notified about requests for my key to be used, allowing me to detect unexpected attempts to use the key. (Any user with root on the development server is also able to forward authentication requests to my laptop.) And I didn't have to type a passphrase every time, so having passphrase-protected key file is much less hassle.