Edward Thomson

A security vulnerability in Git has been announced: a bug in submodule resolution can cause git clone --recursive to execute arbitrary commands.

What's the problem?

When a Git repository contains a submodule, that submodule's repository structure is stored alongside the parent's, inside the .git folder. This structure is generally stored in a folder with the same name as the submodule, however the name of this folder is configurable by a file in the parent repository.

Vulnerable versions of git allow the folder name to contain a path that is not necessarily beneath the .git directory. This can allow an attacker to carefully create a parent repository that has another Git repository checked in, as a folder inside that parent repository. Then that repository that's checked in can be added as a submodule to the parent repository. That submodule's location can be set outside of the .git folder, pointing to the checked-in repository inside the parent itself.

When you recursively clone this parent repository, Git will look at the submodule that has been configured, then look for where to store that submodule's repository. It will follow the configuration into the parent repository itself, to the repository that's been checked in as a folder. That repository will be used to check out the submodule… and, unfortunately, any hooks in that checked-in repository will be run.

So the attacker can bundle this repository configuration with a malicious post-checkout hook, and their code will be executed immediately upon your (recursive) clone of the repository.

Hosting providers

Thankfully, since most of us rely on a hosting provider to store our code, we can stop this vulnerability by simply blocking the repositories there. Visual Studio Team Services is actively blocking any repository that tries to set up a git submodule outside of the .git directory. I'm told that GitLab and GitHub are, too, and presumably other hosting providers are blocking these malicious repositories as well.

Upgrade your client

Blocking these repositories on the hosting providers shuts down an important attack vector, and I hope that it's unlikely that you git clone --recursive a repository that you don't trust. Despite that, you should still upgrade your client.

Git version 2.17.1 is the latest and greatest version of Git, and has been patched. But most people don't actually build from source, so your version of Git is probably provided to you by a distribution. You may have different versions available to you - ones that have had the patches applied by your vendor - so you may not be able to determine if you're vulnerable simply by looking at the version number.

Here's some simple steps to determine whether you're vulnerable and some upgrade instructions if you are.

Are you vulnerable?

You can easily (and safely) check to see if your version of Git is vulnerable to this recent security vulnerable. Run this from a temporary directory:

git init test && \
  cd test && \
  git update-index --add --cacheinfo 120000,e69de29bb2d1d6434b8b29ae775ad8c2e48c5391,.gitmodules

Note: this will not actually clone any repositories to your system, and it will not execute any dangerous commands.

If you see:

error: Invalid path '.gitmodules'
fatal: git update-index: --cacheinfo cannot add .gitmodules

Congratulations - you are already running a version of Git that is not vulnerable.

If, instead, you see nothing, then your version of Git is vulnerable and you should upgrade immediately.

Windows

Windows is quite easy to upgrade. Simply grab the newest version of Git for Windows (version 2.17.1) from https://gitforwindows.org/.

macOS

Apple ships Git with Xcode but unfortunately, they do not update it regularly, even for security vulnerabilities. As a result, you'll need to upgrade to the version that is included by a 3rd party. Homebrew is the preferred package manager for macOS.

  1. If you have not yet installed Homebrew, you can install it by running:

    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    

    at a command prompt.

  2. After that, you can use Homebrew to install git:

    brew install git
    
  3. Add the Homebrew install location (/usr/local) to your PATH.

    echo 'export PATH="/usr/local/bin:$PATH"' >> ~/.bashrc
    
  4. Close all open Terminal sessions, quit Terminal.app, and re-open it.

Linux (Debian, Ubuntu)

If you're using the current version of Ubuntu or Debian, then they'll have the latest version ready. If you're on a stable system, like a server, you should be running an LTS release - a "long term support" version - where they backport security patches like this one. So you should simply need to:

  1. Get the latest information about the available software versions from the remote repository:

    Debian, Ubuntu:

    sudo apt-get update
    

    Red Hat, CentOS:

    sudo yum update
    
  2. Install the latest version of git:

    Debian, Ubuntu:

    sudo apt-get install git
    

    Red Hat, CentOS:

    sudo yum update git
    

Ensuring that you're patched

Now if you run:

git init test && \
  cd test && \
  git update-index --add --cacheinfo 120000,e69de29bb2d1d6434b8b29ae775ad8c2e48c5391,.gitmodules

at a command prompt, then you should see:

error: Invalid path '.gitmodules'
fatal: git update-index: --cacheinfo cannot add .gitmodules

And now you're patched against the git security vulnerability, CVE 2018-11234 and CVE 2018-11235.

Thanks to Junio Hamano, Jeff King, Johannes Schindelin and the rest of the Git security community for their work to keep our source code safe and secure.

If you're interested in security vulnerabilities in Git, please join me at NDC Oslo, where I'll talk you through the details of this security issue and others.