A critical vulnerability was identified in Git last week. This has been fixed in all maintained versions of Git (v188.8.131.52, v1.9.5, v2.0.5, v2.1.4, and v2.2.1) so upgrading is the best way to protect yourself. However a sensible second step is to secure your Git hosting server, so that pushes containing malicious trees are automatically rejected. This will prevent attackers from exploiting users who have yet to upgrade their local versions of Git.
The fix outlined below is based on our Git hosting server,
Atlassian Stash. But it will also work for other repository hosting
solutions that use the native
git-receive-pack binary to accept pushes from
clients, so read on even if you aren't yet using Stash for Git repository
Git stores all of its data in the
.git/ directory in the root of your
$ ls .git HEAD description info refs config hooks objects
When Git checks out files, it has built-in safeguards to prevent it from
overwriting the contents of
.git/. Prior to the vulnerability being fixed,
these safeguards were not sufficient for protection on certain file systems.
Although it is not possible to check out a tree named
.git in your
repository, it was possible to create a malicious tree with different case,
.GIT. This is a problem on case-insensitive
file systems, including OS X (HFS+) and Windows (FAT/NTFS), because Git would
happily write out the contents of a maliciously constructed tree over the
This vulnerability can be used to write the contents of any file in
including modifying or creating executable files in
.git/hooks/. These are
scripts that run at various points of the lifecycle of certain Git commands:
$ ls .git/hooks applypatch-msg pre-applypatch pre-rebase commit-msg pre-commit prepare-commit-msg post-update pre-push update
Being able to modify these scripts effectively allows an attacker to execute
arbitrary commands on your machine. Defining malicious git aliases by
overwriting the user's
.git/config is another potential attack vector.
On Windows, users are also susceptible to a variation of this vulnerability
where the tree
git~1 is mapped onto
.git by the filesystem.
Git users on OS X are susceptible to another variation where the HFS+ filesystem
ignores certain unicode codepoints. A tree named
.gi\u200ct will be
.git and again overwrite the contents of your
To exploit this vulnerability, an attacker would need to craft a commit containing a malicious tree and push it to a repository frequented by the intended victim. The victim would then need to pull a branch or tag containing the malicious commit and subsequently check it out to be exploited.
An attacker needs write access to a repository in order to push the malicious changes in the first place. The actual risk for most teams' repositories is relatively low, as there is typically a high level of trust between those who have the necessary permissions to write to a repository.
However, all developers should exercise caution when pulling from third party or untrusted repositories until they upgrade to a patched version of Git.
The best fix is for users to upgrade the version of Git installed on their machines. This will ensure that they are protected when pulling from any repository, trusted or otherwise.
A good second line of defence is to configure your Git server to ensure that malicious commits can not be pushed to them.
There are two things you need to do to protect your Git server:
- Upgrade the version of Git installed on your server to v2.2.1 or newer. Earlier maintenance releases have also been patched so v184.108.40.206, v1.9.5, v2.0.5 or v2.1.4 are fine too.
- Enable the following Git settings:
receive.fsckObjects makes Git check the integrity of objects before
a push is accepted, which is a pre-requisite for the other flags.
core.protectNTFS flags prevent the OS X and
Windows vulnerabilities described above, respectively. Both default to
on their respective systems but will need to be enabled specifically on other
platforms. Since clients could be using a different operating system to your
server you should enable both.
You can apply these settings one of two ways:
globally, by running the following commands as the user that Git runs as during hosting operations (this is
atlstashif you used the installer to install Stash):
git config --global --bool receive.fsckObjects true git config --global --bool core.protectHFS true git config --global --bool core.protectNTFS true
per repository, by looping over each repository and configuring them individually. If you're hosting on Linux you can run the following command from the parent directory containing all of your repositories:
for repo in `ls -d */`; do echo $repo; cd $repo; git config --bool receive.fsckObjects true; git config --bool core.protectHFS true; git config --bool core.protectNTFS true; cd ..; done
In Stash 3.2+ run the command in:
In earlier versions of Stash run the command in:
There will be a patched version of Stash in the near future that will apply these settings automatically, so if you work in a team where your developers are unlikely to exploit each other, you may opt to wait for the patch.
Testing existing repositories
If you're concerned that one or more of your repositories may already have been
compromised, you can check to see if it contains a malicious tree using
git fsck (after upgrading Git). It will print out a warning if the
repository contains a tree that maps to
$ git fsck Checking object directories: 100% (256/256), done. warning in tree 360d9613c584ceb6e8c32bca6c69ed318d9dbbfd: contains '.git' Checking objects: 100% (5/5), done.
You can run this in a loop and check the output to see if you have any such trees in your repositories:
for repo in `ls -d */`; do echo $repo; cd $repo; git fsck; cd ..; done
If you do find a malicious tree, you can then
git rebase it out
of the history of the affected repository. Note that you may see some other
odd warnings relating to the structure of your repository that are not
necessarily problems (e.g.
notice: HEAD points to an unborn branch (master)
for an emptry repository).