45

How safe are signed git tags? Especially because git uses SHA-1. There is contradictory information around.

So if one verifies a git tag (git tag -v tagname), then checksouts the tag, and checks that git status reports no untracked/modified files, without further manually auditing the code, how secure is this actually? Is it only as safe as SHA-1?

Let's assume an adversary, that is capable of producing SHA-1 collisions.

Linus Torvalds said.

Git uses SHA-1 not for security

And goes on.

The security parts are elsewhere

Could you please elaborate on this? Where are the security parts? Can you please briefly explain how these work? Where can I read more about this?

Wikipedia says.

Nonetheless, without second preimage resistance of SHA-1 signed commits and tags would no longer secure the state of the repository as they only sign the root of a Merkle tree.

(preimage resistance | Merkle tree)

Which contradicts what Linus Torvalds said. What does that mean for security? Which statement is true?

Sources:

The source control management system Git uses SHA-1 not for security but for ensuring that the data has not changed due to accidental corruption. Linus Torvalds has said, "If you have disk corruption, if you have DRAM corruption, if you have any kind of problems at all, Git will notice them. It's not a question of if, it's a guarantee. You can have people who try to be malicious. They won't succeed. [...] Nobody has been able to break SHA-1, but the point is the SHA-1, as far as Git is concerned, isn't even a security feature. It's purely a consistency check. The security parts are elsewhere, so a lot of people assume that since Git uses SHA-1 and SHA-1 is used for cryptographically secure stuff, they think that, OK, it's a huge security feature. It has nothing at all to do with security, it's just the best hash you can get. [...] I guarantee you, if you put your data in Git, you can trust the fact that five years later, after it was converted from your hard disk to DVD to whatever new technology and you copied it along, five years later you can verify that the data you get back out is the exact same data you put in. [...] One of the reasons I care is for the kernel, we had a break in on one of the BitKeeper sites where people tried to corrupt the kernel source code repositories."

Update:
Got an verbose answer from Mike Gerwitz, the author of A Git Horror Story: Repository Integrity With Signed Commits:

https://forums.whonix.org/t/security-git-general-verification-verifying-whonix-submodules/513/12

6
  • 5
    Got an verbose answer from Mike Gerwitz, the author of A Git Horror Story: Repository Integrity With Signed Commits: whonix.org/forum/index.php/topic,538.msg4278.html#msg4278
    – adrelanos
    Commented Sep 23, 2014 at 22:31
  • See also the wording of my similar question. Since it has been closed as a duplicate would you ming if I edited in some of the more specific angles into this question?
    – Caleb
    Commented Jan 7, 2015 at 19:09
  • I don't mind either way.
    – adrelanos
    Commented Jan 7, 2015 at 22:26
  • Linus actually did admit that signed tags are a bit of an exception: "The one exception: the "signed tags" security does depend on the hashes being cryptographically strong. So again, breaking SHA-1 would not mean that git stops working, but it would potentially mean that if you don't trust your own private repository, the signed tag may no longer protect you entirely" (See spinics.net/lists/git/msg09588.html)
    – Ajedi32
    Commented Feb 23, 2017 at 20:39
  • Mike Gerwitz implies a repository may be trusted if every single commit is signed. He doean't address if this secures non-commit objects such as blob and tree, and he ignores that repos may have more-easily-attackable binary data committed to them.
    – fuzzyTew
    Commented Feb 24, 2017 at 18:46

3 Answers 3

22

There is no contradiction. Linus himself said in that same talk:

If I have those 20 bytes, I can download a git repository from a completely untrusted source and I can guarantee that they did not do anything bad to it.

I'd interpret the "Git uses SHA-1 not for security" as "SHA-1 hasn't been added to git for security reasons, but for reliability reasons, but security still is a nice side effect", and "The security parts are elsewhere" as "the final verification is done by gpg, and git verify-tag".

Git commit ids aren't "more secure" than "bare" SHA-1. However, the use cases git is used for are more resistant against collision attacks, than most other SHA-1 use cases.

For example, SHA-1 in certificates is dangerous. Somebody could create two certificates with the same hash and for different domain names. One (the "legitimate" one) is sent in a CSR to a CA, and the other one kept private until used on some victim with the signature from the CA. For collision attacks, if the attacker changes the preimage at one part (like the domain name field of the cert), they must also change it at another position. While the attacker had free choice for the two domain names, the other changes are mostly fixed. Particularly, they are binary, and can't be part of any human-readable part of the cert. Some attacks hide them in the public/private keys of the cert (discussion for MD5).

Git however, is mostly used for source code. Hiding your {chosen-prefix,} collision in an ASCII diff reviewed by humans is much harder. Maintainers usually ask questions when you make an if-condition about the hex address 2ff5e of the file logo.png you added in the commit. Taken together, it is easier to hide a backdoor inside a commit, than to attack SHA-1.

2
  • 14
    The heartbleed morass challenges the mantra "Maintainer can spot the change". Commented Sep 23, 2014 at 6:13
  • 1
    It might be worth updating this in light of security.stackexchange.com/q/152142/96753. I think the whole answer still applies, but still worth reviewing.
    – Wildcard
    Commented Feb 24, 2017 at 4:51
7

Signed git tag is just a signed SHA1 checksum. Very simply said, every git commit is SHA1 checksum of the previous commit (which also contains SHA1 of its previous commit which also contains SHA1 checksum of its previous commit and so...).

If you find a way, how to change something in a repository, keeping the SHA1 unchanged (you find a collision), then you can break the signature.

Keep in mind that git is distributed VCS. Usually, there are many people who have their own clones. It would be quickly spotted, if there was something wrong.

Also, there is a big difference between finding a collision and finding particular collision. For instance, it is easy to find 2 "random" different data with the same MD5 sum. But AFAIK, how to change the given data just slightly and keep MD5 unchanged is still a hard problem and SHA1 is much stronger then MD5.

Nevertheless, If somebody managed to find a way how to find SHA1 collisions easily, then git would have much bigger problem. Git uses SHA1 as every object index. If you try to commit SHA1 collided object you would probably break (...I'm not sure there...) at least the commit.

2
  • 3
    What was Linus talking about then? Git uses SHA-1 not for security [...] The security parts are elsewhere
    – adrelanos
    Commented Sep 23, 2014 at 1:23
  • He probably wasn't talking about signatures. He probably mentioned something different. In comparison to other VCS you always clone whole repo which is kind of mass backup and consistency check.
    – smrt28
    Commented Sep 23, 2014 at 6:18
0

The following is my understanding.

Git identifies pretty much everything by sha1 hashes. Your signed tag references the commit by it's sha1 hash, the commit identifies the "tree" by it's sha1 hash and the "tree" references the file "blobs" by their sha1 hashes.

So if you have two files that are represented by "blobs" with the same sha1 hash then you could replace one with the other and the signed tag would still validate just fine.

The git hashing of objects prepends a header with the type and size, this means that collisions used to attack git must be prepared specifically to attack git but doesn't present any real problems beyond that.

Practically I think the risk depends heavily on what you keep in your git repos. We don't have a preimage attack for SHA1 and we are unlikely to have any time soon. So we only have to worry about collision attacks.

If it is human readable source code reviewed by human reviewers then the risk is small. If someone can slip in a block of unexplained binary garbage and a conditional that does evil stuff based on the content of that block of binary garbage they can probably slip in malicious stuff without having to bother about sha1 collisions.

OTOH if it is being used to store binaries originated from untrusted sources there is more potential for trouble.


" we are unlikely to have any time soon" - hmm. "Attacks only get better".

Preimage attacks are a LOT harder than collision attacks. A decade after the first collisions were demonstrated for MD5 we still don't have a feasible preimage attack.

I would be more worried about two commits which contain "jpeg + innocent code" and "jpeg + evil code"

The complication is due to the way git commits are structured the jpeg data and the code would have to be in the same file. I guess it could be an issue if people are storing tarballs in their git repo or something like that.

Another possible scenario would be if some code decided what to do with a file based on automatic file type detection. If a "distinct chosen prefix" collision becomes practical then someone could commit an innocuous looking binary file (an image or so) that happened to have a bunch of garbage in it somewhere. Then replace it with a more dangerous file.

For comparison with md5 it took about 2 years to go from basic collisions to distinct chosen prefix collisions.

3
  • " we are unlikely to have any time soon" - hmm. "Attacks only get better". I would be more worried about two commits which contain "jpeg + innocent code" and "jpeg + evil code" and getting the good commit signed then distributing the evil code. Commented Feb 24, 2017 at 8:36
  • That's kinda wrong. "git doesn't actually just hash the data, it does prepend a type/length field to it" You can verify this for yourself. Try replacing a know .pdf with another with the same hash, and you would see Git noticing the change. (That, unlike Subversion.)
    – sanmai
    Commented Apr 21, 2019 at 9:52
  • The prepended type/length just means you have to do your attack calculations based on what git hashes rather than based on the plain files. It's not a major obstaticle. Commented May 1, 2019 at 14:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .