Weak cryptographic standards removal notice

Last year we announced the deprecation of several weak cryptographic standards. Then we provided a status update toward the end of last year outlining some changes we'd made to make the transition easier for clients. We quickly approached the February 1, 2018 cutoff date we mentioned in previous posts and, as a result, pushed back our schedule by one week. On February 8, 2018 we'll start disabling the following:

  • TLSv1/TLSv1.1: This applies to all HTTPS connections, including web, API, and git connections to https://github.com and https://api.github.com.
  • diffie-hellman-group1-sha1: This applies to all SSH connections to github.com
  • diffie-hellman-group14-sha1: This applies to all SSH connections to github.com

We'll disable the algorithms in two stages:

  • February 8, 2018 19:00 UTC (11:00 am PST): Disable deprecated algorithms for one hour
  • February 22, 2018 19:00 UTC (11:00 am PST): Permanently disable deprecated algorithms

For more details, head to the Engineering Blog.

Game Off, our annual game jam returns in November

GitHub Game Off 2017

Game Off—our fifth annual game jam returns in just two weeks!

A game jam is a hackathon for creating video games. Although most game jams run for 24-72 hours, the Game Off runs for the entire month of November. You'll have 30 days to create a game inspired by or loosely based on a theme that we'll announce Wednesday, November 1, at 13:37 pm PDT.

As always, you're encouraged to use open source game engines, libraries, and tools, but you're free to use any technology you want. It's a perfect excuse to experiment with something new, too.

This year, the Game Off will take place on itch.io–an open marketplace for indie game developers and platform for running game jams among other things. Best of all, this year, you'll be the judging the entries.

We'll announce all the latest updates on our blog and Twitter account. Stay tuned and follow along with the #GitHubGameOff hashtag!

Join the jam on itch.io today

GLHF! We can't wait to see play what you make <3

Doubling Bug Bounty rewards

Hack the World 2017

We're coming up on four years since the Bug Bounty program was first announced. A lot has changed in that time, and we constantly try to keep our reward structure inline with top security bug bounty programs. We're excited to announce that starting today we're doubling our payout amounts, bringing the minimum and maximum payouts to $555 and $20,000, respectively. This means that any report eligible for a bounty will be met with at least a $555 reward. This doesn't mean we're raising the bar for what is considered a valid report, we're simply raising the payouts.

This bump to our payouts aligns with Hack the World, an annual hacking competition by HackerOne, which kicked off this morning and runs until November 18th. During this time participants compete against each other to find the most security vulnerabilities across all sites on HackerOne's platform. We're one of the sponsors, which means hackers will be rewarded with twice the reputation points on HackerOne when finding bugs on GitHub over the next month! As an additional incentive, we will also be rewarding all valid submissions with free unlimited private repositories for life. The increased bounty payouts are here to stay, but unlimited private repositories will only rewarded on reports submitted on or before November 18th!

Ready to compete? Submit all reports to our Bug Bounty program. For more details on the competition, please visit the Hack the World website.

Git LFS 2.3.0 released


Git LFS v2.3.0 is now available with performance improvements to git lfs migrate and git clone, new features, bug fixes, and more.

Download Git LFS v2.3.0

git lfs migrate

With our latest release, git lfs migrate ships with a native implementation for reading packed objects: an important next step to making Git LFS's migrator performance significantly faster. Git LFS also learned how to avoid saving unchanged objects, making it 52% faster[1] to examine your repository for large objects than in previous releases.

~/g/git-lfs (master) $ git lfs version
git-lfs/2.2.1 (GitHub; darwin amd64; go 1.8.3; git 621d1f82)

/g/git-lfs (master) $ time git lfs migrate info
migrate: Sorting commits: ..., done
migrate: Rewriting commits: 100% (5840/5840), done
# ...
git lfs migrate info  36.30s user 19.80s system 147% cpu 38.127 total
~/g/git-lfs (master) $ git lfs version
git-lfs/2.3.0 (GitHub; darwin amd64; go 1.8.3; git 70995b39)

~/g/git-lfs (master) $ time git lfs migrate info
migrate: Sorting commits: ..., done
migrate: Examining commits: 100% (5840/5840), done
# ...
git lfs migrate info  23.74s user 5.71s system 162% cpu 18.144 total

git clone

The git clone command is now 170% faster on repositories using Git LFS than in previous releases.[2] That means the native git clone command is as fast as the (now deprecated) git lfs clone wrapper. With simultaneous object batching and transferring, you can expect dramatic performance improvements for tools that shell out to git clone or git checkout.

You'll also find support for new transfer agents, release targets, documentation, and more—all of which are thanks to gracious contributions from the Git LFS open source community.

For more information about the Git LFS v2.3.0 release, check out the release notes.

The data science behind topic suggestions

Add topics to repositories

Earlier this year, we launched topics, a new feature that lets you tag repositories with descriptive words or phrases. Topics help you create connections between similar GitHub projects and explore them by type, technology, and other characteristics they have in common.

All public repositories show topic suggestions, so you can quickly tag repositories with relevant words and phrases. These suggestions are the result of some exciting data science work—in particular, a topic extraction framework based on text mining, natural language processing, and machine learning called repo-topix.

Learn more about repo-topix from the Engineering Blog

Topic suggestions close up

Now when you add or reject topics, you're doing more than keeping projects organized. Every topic will contribute to surfacing connections and inspiring discovery across GitHub. Repository names, descriptions, and READMEs from millions of public projects serve as the very start of an ever-evolving knowledge graph of concepts. Eventually, the graph will map how these concepts relate to each other and to the code, people, and projects on GitHub.

Topics is part of a greater effort to use our public data to make meaningful improvements to how people discover, interact, and build on GitHub. We'll be sharing more ways that data can improve the way you work at Universe—our flagship product and community conference.

Get tickets to GitHub Universe

GitHub for Unity 0.19-alpha released

GitHub for Unity 0.19-alpha

Our GitHub for Unity 0.19-alpha "Swashbuckler" release is now available with much improved Mac support, bug fixes, and performance improvements—many added by the community.

Here are a few highlights since our last Unity update.

Improved macOS support

GitHub for Unity for Mac should now have the same features and functionality (and bugs!) as the Windows version. Thanks to a custom fork of Axosoft's NSFW library, our SFW Library provides us with a file watcher to refresh the UI consistently across platforms.

No more garbled commit messages!�

Goodbye U+FFFD � replacement character

Say goodbye to all those �s that you may have seen in your commit history. Thanks to @shiena, commit messages will start looking less like:


And more like:


Thanks also to Dazzle for your commitment to open source.

Commit with style

Thanks again to @shiena, commit logs will now follow the recommended style, meaning they'll look a lot less like this:

Increase the health of baddies by 1.75
Beta testers reported that defeating the baddies felt too easy.

And a lot more like this:

Increase the health of baddies by 1.75

Beta testers reported that defeating the baddies felt too easy.

This is beneficial for a variety of reasons, but consider the one person on your team who's still using the command line. Commands like git log and git shortlog will be a lot more useful when the commit subject and body are clearly separated:

$ git log
commit 651733e0206a4a0c1b0e24d4a5b9e7c5973d47bf
Author: Lee Reilly <lee@github.com>
Date:   Thu Aug 24 13:37:00 2017 -0200

 Add Discord library

 Our players want to talk to one another, so this adds some basic
 integration to provide (1) basic text chat and (2) experimental
 voice chat.

commit fcf7d51d8d6d172e3d241cdbe7180f0a303e9292
Author: Don Okuda <don@github.com>
Date:   Wed Aug 23 21:18:28 2017 -0700

 Added some baddies

 Beta testers reported that defeating the baddies felt too easy.


Finally, @MunchyYDL applied best practices to our views and picked up the first of our up-for-grabs issues—specifically, using EditorGUI.BeginDisabledGroup() and EditorGUI.EndDisabledGroup() rather than setting GUI.enabled().

Oh, and congratulations on your first pull request, @MunchyYDL!

Marcus Christensen's first pull request

You'll find the complete list of new features, improvements, and bug fixes in the release notes. Many thanks to our community for your contributions during the alpha.

Please note: If you're upgrading to the latest version, the plugin location has moved to Assets/Plugins/GitHub. You'll need to exit Unity completely and delete the Assets/Editor/GitHub folder before installing the latest version. Hey, we told you it was an alpha.

Be part of the Unity for GitHub Alpha

The alpha release is available for free to all GitHub and Unity users.

Download the latest release now

Easily filter review requests by team

Review requests are a great way to ask for review on software, and with the addition of team requests you can get the feedback you need faster.

To make it easier to find pull requests that need your review, you can now see them all alongside any team you're a member of just by using the review-requested:nplasterer filter. If that's not enough, and you'd like to search for team requests directly you can also use a team search: team-review-requested:github/octocats. This change will also be updating what displays in your global Review Request tab.
A screenshot showing the global review requests dashboard

Qualifier Notes
review:none Returns pull requests that have not been reviewed
review:required Returns pull requests that have not been reviewed but have a protected branch
review:approved Returns approved pull requests
review:changes_requested Returns pull requests that have requested changes
reviewed-by:USERNAME Returns pull requests that have been reviewed by the specified user
review-requested:USERNAME Now returns pull requests that have direct requests and team requests
team-review-requested:TEAMNAME Returns pull requests with requests for the specified team

We hope this new search filter helps you organize your work and review code more efficiently! Check out the documentation to learn more, or drop any questions, comments, or feedback into our help form.

GitHub for Unity 0.16-alpha released

$GitHub for Unity 0.16-alpha

We announced GitHub for Unity at the Games Developer Conference back in March and open sourced it at Unite Europe in June. Thanks to our contributors and more than a month of effort, version 0.16-alpha is now available.

Download the latest release

Highlights from the release notes

Support for Unity 2017

GitHub for Unity now works with the latest Unity 2017 release.

Publish new repositories

Now you can publish repositories to GitHub without leaving the comfort of Unity.

You can now publish repositories in GitHub for Unity

Delete old branches

Branching is a safe and easy way to introduce new features, work on bug fixes, or experiment with that idea you had in the shower.

Whether your branch is meant for merging or just sharing with a teammate, you may want to delete it at some point. Now you can without switching to the command line or googling "How do I delete a Git branch both locally and remotely?".

Delete old branches in GitHub for Unity

Special thanks to @CapnRat for leveling up the authentication workflow with github-for-unity/Unity/pull/58. You can now use Enter / Return as confirmation keys when you're in the authentication flow.

Download the latest release of GitHub Unity, view the full release notes—or contribute back to help us reach version 1.0. Your feature requests, bug reports, and pull requests are all welcome. Onwards!

Introducing Soft U2F, a software U2F authenticator for macOS

Soft U2F - Software U2F authenticator for macOS

In an effort to increase the adoption of FIDO U2F second factor authentication, we're releasing Soft U2F—a software-based U2F authenticator for macOS.

Soft U2F currently works with Google Chrome and Opera's built-in U2F implementations, as well as with the U2F extensions for Safari and Firefox.

When a site loaded in a U2F-compatible browser attempts to register or authenticate with the software token, you'll see a notification asking you to accept or reject the request. You can experiment on Yubico's U2F demo site:

U2F authentication with Soft U2F

And as of today, you can download the Soft U2F installer and configure it for use with your GitHub account.

Interested in learning more? Head over to our Engineering Blog and read more about the motivations for the project plus the security considerations of hardware vs. software key storage.

Git LFS 2.2.0 released

Git LFS v2.2.0 is now available

Git LFS v2.2.0 is now available with the all new git-lfs-migrate command, making it easier than ever to start using Git LFS in your repository.

For example, if you've tried to push a large file to GitHub without LFS, you might have seen the following error:

$ git push origin master
# ...
remote: error: gh001: large files detected. you may want to try git large file storage - https://git-lfs.github.com.
remote: error: see http://git.io/iept8g for more information.
remote: error: file a.psd is 1.2 gb; this exceeds github's file size limit of 100.00 mb
to github.com:ttaylorr/demo.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@github.com:ttaylorr/demo.git'

You can use the git lfs migrate info command to see which files are causing the push failure:

$ git lfs migrate info
*.psd   1.2 GB   27/27 files(s)  100%

Using the information above, you can determine which files to pluck out of your history and store in LFS:

$ git lfs migrate import --include="*.psd"
migrate: Sorting commits: ..., done
migrate: Rewriting commits: 100% (810/810), done
  master        f18bb746d44e8ea5065fc779bb1acdf3cdae7ed8 -> 35b0fe0a7bf3ae6952ec9584895a7fb6ebcd498b
migrate: Updating refs: ..., done

$ git push origin
Git LFS: (1 of 1 files) 1.2 GB / 1.2 GB
# ...
To github.com:ttaylorr/demo.git
 * [new branch]      master -> master

You can also configure the 'import' command to migrate specific filetypes, branches, and more. For a detailed overview, take a look at the man page.

This was a quick look at the migrate command available today in Git LFS v2.2.0. For more on the full release, check out the release notes.

Git 2.13 has been released

The open source Git project has just released Git 2.13.0, with features and bugfixes from over 65 contributors. Before we dig into the new features, we have a brief security announcement.

For those running their own Git hosting server, Git 2.13 fixes a vulnerability in the git shell program in which an untrusted Git user can potentially run shell commands on a remote host. This only affects you if you're running a hosting server and have specifically configured git shell. If none of that makes sense to you, you're probably fine. See this announcement for more details. As neither GitHub.com nor GitHub Enterprise uses git shell, both are unaffected.

Phew. With that out of the way, let's get on to the fun stuff.

SHA-1 collision detection

Did I say fun? Oops, we're not there yet.

You may have heard that researchers recently found the first collision in SHA-1, the hash function Git uses to identify objects. Their techniques may eventually be used to conduct collision-based attacks against Git users. Fortunately those same researchers also provided a way to detect content that is trying to exploit this technique to create collisions. In March, GitHub.com began using that implementation to prevent it being used as a potential platform for conducting collision attacks.

Git 2.13 ships with similar changes, and will detect and reject any objects that show signs of being part of a collision attack. The collision-detecting SHA-1 implementation is now the default. The code is included with Git, so there's no need to install any additional dependencies. Note that this implementation is slower than the alternatives, but in practice this has a negligible effect on the overall time of most Git operations (because Git spends only a small portion of its time computing SHA-1 hashes in the first place).

In other collision detection news, efforts have continued to develop a transition plan and to prepare the code base for handling new hash functions, which will eventually allow the use of stronger hash algorithms in Git.

[collision detection, SHA-1 transition 1, SHA-1 transition 2]

More convenient pathspecs

You've probably passed path arguments to Git before, like:

$ git log foo.c
$ git grep my_pattern program.rb

But you may not have known that to Git, the foo.c and program.rb arguments are actually pathspecs, a Git-specific pattern for matching paths. Pathspecs can be literal paths, prefixes, or wildcards:

$ git log Documentation/      # Everything under the Documentation/ directory
$ git log '*.c'               # C files anywhere in the tree

But they also have a powerful extension syntax. Pathspecs starting with :(magic) enable special matching features. The complete list can be found in the pathspec section of git help glossary, but let's look at a few here.

For instance, you may want to exclude some files from a grep, which you can do with the :(exclude) directive:

$ git grep this.is.a src
src/foo.c:this is a C file
src/foo.rb:this is a ruby file

$ git grep this.is.a -- src ':(exclude)*.c'
src/foo.rb:this is a ruby file

There are a few things to note in that example. The first is that we had to put our pathspec after a -- (double-dash) separator. This is necessary because most Git commands actually take a combination of revisions and pathspecs. The full syntax is [<revisions>] -- [<pathspecs>]. If you omit the double-dash, Git will check each argument to see if it's either a valid object name or a file in the filesystem. But since our exclude pattern is neither, without the double-dash Git would give up and complain (this may change in a future version of Git; wildcards like *.c used to have the same problem, but the rules were recently loosened to resolve them as pathspecs). More information is available via git help cli.

The second thing to note is that typing :(exclude) is a pain, and we have to quote it from the shell. But there's a solution for that: short form pathspec magic. The short form for exclude is ! (exclamation point). This is easy to remember, since it matches the syntax in other parts of Git, like .gitignore files.

$ git grep this.is.a -- src ':!*.c'
src/foo.rb:this is a ruby file

That's shorter than exclude, but we still have to quote, since the exclamation point triggers history expansion in most shells. Git 2.13 adds ^ (caret) as a synonym for the exclamation point, letting you do the same thing without any shell quoting:

$ git grep this.is.a -- src :^*.c
src/foo.rb:this is a ruby file

Ah, much better. Technically we would need to also quote the *.c wildcard from the shell, but in practice it works out. Unless you have a file that starts with :^ and ends in .c, the shell will realize that the wildcard matches nothing and pass it through to Git verbatim.

But wait, there's more! Git 2.13 also adds the attr token, which lets you select files based on their gitattributes values. For instance, if you use Git LFS, you may want to get a list of files which have been configured to use it:

$ git ls-files

$ git ls-files ':(attr:filter=lfs)'

You can even define your own attributes in order to group files. Let's say you frequently want to grep a certain set of files. You can define an attribute, and then select those files using that attribute:

$ echo 'libfoo/ vendored' >>.gitattributes
$ echo 'imported-tool/ vendored' >>.gitattributes
$ git grep -i license -- ':(attr:vendored)'

And if you want to get really fancy, you can combine the attr and exclude tokens:

$ git grep foobar -- ':(exclude,attr:vendored)'

Note that the attr token is not yet supported in all parts of the code. Some commands may report that it cannot be used with them, but this is likely to be expanded in future versions of Git.

[negative pathspecs, attribute pathspecs]

Conditional configuration

Git's configuration system has several levels of priority: you can specify options at the system level, the user level, the repository level, or for an individual command invocation (using git -c). In general, an option found in a more specific location overrides the same option found in a less specific one. Setting user.email in a repository's .git/config file will override the user-level version you may have set in ~/.gitconfig.

But what if you need to set an option to one value for a group of repositories, and to another value for a different group? For example, you may use one name and email address when making commits for your day job and another when working on open source. You can set the open source identity in the user-level config in your home directory and then override it in the work repositories. But that's tedious to keep up to date, and if you ever forget to configure a new work repository, you'll accidentally make commits with the wrong identity!

Git 2.13 introduces conditional configuration includes. For now, the only supported condition is matching the filesystem path of the repository, but that's exactly what we need in this case. You can configure two conditional includes in your home directory's ~/.gitconfig file:

[includeIf "gitdir:~/work/"]
  path = .gitconfig-work
[includeIf "gitdir:~/play/"]
  path = .gitconfig-play

Now you can put whatever options you want into those files:

$ cat ~/.gitconfig-work
name = Serious Q. Programmer
email = serious.programmer@business.example.com

$ cat ~/.gitconfig-play
name = Random J. Hacker
email = rmsfan1979@example.com

The appropriate config options will be applied automatically whenever you're in a repository that's inside your work or play directories.

[conditional includes]

Bits and bobs

  • --decorate=auto is now the default for git log. When output is sent to the user's terminal, commits that are pointed to directly by a branch or tag will be "decorated" with the name of the branch. [source]

  • git branch's output routines have been ported to the ref-filter system shared by git for-each-ref and git tag. This means you can now use git branch --format= to get custom output. See git help for-each-ref for the list of substitutions. As a side note, these patches are from Karthik Nayak, Git's Google Summer of Code student from 2015. Though his GSoC project to introduce ref-filter was completed almost two years ago, he's continued contributing to the project. Great work! [source]

  • git branch, git tag, and git for-each-ref all learned the --no-contains option to match their existing --contains option. This can let you ask which tags or branches don't have a particular bug (or bugfix). [source]

  • git stash now accepts pathspecs. You can use this to create a stash of part of your working tree, which is handy when picking apart changes to turn into clean commits. [source]

  • The special branch names @{upstream}, @{u}, and @{push} are now case-insensitive. This is especially convenient as both @ and { require holding down the shift key on most keyboards, making it easy to accidentally type a capital U. Now you can hold that shift key AS LONG AS YOU WANT. [source]

  • More commands have learned to recurse into submodules in the past few versions of Git, including checkout, grep, and ls-files. git status --short also now reports more information about submodules. [source, source, source, source]

  • The last few versions of Git have cleaned up many corner cases around repository discovery and initialization. As a final step in that work, Git 2.13 introduced a new assertion to catch any cases that were missed. After being tested for months in development versions, this shouldn't trigger. But it's possible that you may see BUG: setup_git_env called without repository. If you do, please consider making a bug report. [source]

The whole kit and caboodle

That's just a sampling of the changes in Git 2.13, which contains over 700 commits. Check out the the full release notes for the complete list.

Protect your organization's repositories with new security settings

Organization owners can now limit the ability to delete repositories. The new repository deletion setting is available for all plans hosted by GitHub and will be coming to GitHub Enterprise soon.

The setting is enabled by default, allowing organization members with admin permissions for a repository to delete it. When the feature is disabled, only organization owners will be able to delete the repository.

how to set repository deletion settings

When deleting a repository, you'll still see Danger Zone warnings. If the repository deletion setting is disabled and you are not an organization admin, you'll get a message letting you know that only owners can delete the repository.

image 2017-04-12 at 9 40 54 pm

Coming soon in the next GitHub Enterprise release

The next GitHub Enterprise release will include the same organization setting for repository deletion. In addition, there will be an appliance-level override that will limit repository deletion to only site-administrators.

The appliance-level setting is enabled by default. This allows users with admin permissions for a repository to delete it and defers to the organization-level repository deletion setting. If disabled, only site administrators will be able to delete the repository.

how to set GitHub Enterprise appliance-level repository deletion settings

When the appliance-level setting is disabled, users will see a similar message as they would at the organization-level when trying to delete a repository.

Documentation and support

For more information about limiting repository deletion for your organization, see our help documentation on deleting repositories. You can learn more about how repository deletion will work on GitHub Enterprise when the next version is released.

If you have any questions, please get in touch with us. We'd be happy to help!

Integrations moves into pre-release with new features

Last September, we launched the Early Access Program of GitHub Integrations, a new option for extending GitHub. We've recently added some new features and moved Integrations into pre-release so you can begin using it within your production workflows. Here's a summary of the latest features. You can learn more about what's changed from our Developer Blog.

Enabling users to log in from your Integration

Users can now log in with your Integration using the OAuth protocol, allowing you to identify users and display data to them from the relevant installations. Additionally, an Integration can now make authorized API requests on behalf of a user; for example, to deploy code or create an issue. Learn more about authenticating as a user via an Integration.

Updating an Integration's permissions

When you create an Integration, you have to specify which permissions it needs; for example, the ability to read issues or create deployments. Now you can update the requested permissions via Settings > Developer settings > Integrations, whenever the needs of your Integration change. Users will be prompted to accept these changes and enable the new permissions on their installation.

Post-installation setup

Finally, you now have the option to configure a Setup URL to which you can redirect users after they install your integration if any additional setup is required on your end.


More information on getting started can be found on our Developer Blog and in our documentation. We'd also love to hear what you think. Talk to us in the new Platform forum.

Git LFS 2.1.0 released

Today we're announcing the next major release of Git LFS: v2.1.0, including new features, performance improvements, and more.

New features

Status subcommand

With Git LFS 2.1.0, get a more comprehensive look at which files are marked as modified by running the git lfs status command.

Git LFS will now tell you if your large files are being tracked by LFS, stored by Git, or a combination of both. For instance, if LFS sees a file that is stored as a large object in Git, it will convert it to an LFS pointer on checkout which will mark the file as modified. To diagnose this, try git lfs status for a look at what's going on:

On branch master

Git LFS objects to be committed:

converted-lfs-file.dat (Git: acfe112 -> LFS: acfe112)
new-lfs-file.dat (LFS: eeaf82b)
partially-staged-lfs-file.dat (LFS: a12942e)

Git LFS objects not staged for commit:

unstaged-lfs-file.dat (LFS: 1307990 -> File: 8735179)
partially-staged-lfs-file.dat (File: 0dc8537)

Per-server configuration

Git LFS 2.1.0 introduces support for URL-style configuration via your .gitconfig or .lfsconfig. For settings that apply to URLs, like http.sslCert or lfs.locksverify, you can now scope them to a top-level domain, a root path, or just about anything else.

Network debugging tools

To better understand and debug network requests made by Git LFS, version 2.1.0 introduces a detailed view via the GIT_LOG_STATS=1 environment variable:

$ GIT_LOG_STATS=1 git lfs pull
Git LFS: (201 of 201 files) 1.17 GB / 1.17 GB

$ cat .git/lfs/objects/logs/http/*.log
concurrent=15 time=1493330448 version=git-lfs/2.1.0 (GitHub; darwin amd64; go 1.8.1; git f9d0c49e)
key=lfs.batch event=request url=https://github.com/user/repo.git/info/lfs/objects/batch method=POST body=8468
key=lfs.batch event=request url=https://github.com/user/repo.git/info/lfs/objects/batch method=POST status=200 body=59345 conntime=47448309 dnstime=2222176 tlstime=163385183 time=491626933
key=lfs.data.download event=request url=https://github-cloud.s3.amazonaws.com/... method=GET status=200 body=4 conntime=58735013 dnstime=6486563 tlstime=120484526 time=258568133
key=lfs.data.download event=request url=https://github-cloud.s3.amazonaws.com/... method=GET status=200 body=4 conntime=58231460 dnstime=6417657 tlstime=122486379 time=261003305

# ...

Relative object expiration

The Git LFS API has long supported an expires_at property in both SSH authenticate as well as Batch API responses. This introduced a number of issues where an out-of-sync system clock would cause LFS to think that objects were expired when they were still valid. Git LFS 2.1.0 now supports an expires_in property to specify a duration relative to your computer's time to expire the object.

What's next?

The LFS team is working on a migration tool to easily migrate your existing Git repositories with large objects into LFS without the need to write a git filter-branch command. We're also still inviting your feedback on our File Locking feature.

In addition, our roadmap is public: comments, questions, and pull requests are welcomed. To learn more about Git LFS, visit the Git LFS website.

That was a quick overview of some of the larger changes included in this release. To get a more detailed look, check out the release notes.

SHA-1 collision detection on GitHub.com

A few weeks ago, researchers announced SHAttered, the first collision of the SHA-1 hash function. Starting today, all SHA-1 computations on GitHub.com will detect and reject any Git content that shows evidence of being part of a collision attack. This ensures that GitHub cannot be used as a platform for performing collision attacks against our users.

This fix will also be included in the next patch releases for the supported versions of GitHub Enterprise.

Why does SHA-1 matter to Git?

Git stores all data in "objects." Each object is named after the SHA-1 hash of its contents, and objects refer to each other by their SHA-1 hashes. If two distinct objects have the same hash, this is known as a collision. Git can only store one half of the colliding pair, and when following a link from one object to the colliding hash name, it can't know which object the name was meant to point to.

Two objects colliding accidentally is exceedingly unlikely. If you had five million programmers each generating one commit per second, your chances of generating a single accidental collision before the Sun turns into a red giant and engulfs the Earth is about 50%.

Why do collisions matter for Git's security?

If a Git fetch or push tries to send a colliding object to a repository that already contains the other half of the collision, the receiver can compare the bytes of each object, notice the problem, and reject the new object. Git has implemented this detection since its inception.

However, SHA-1 names can be assigned trust through various mechanisms. For instance, Git allows you to cryptographically sign a commit or tag. Doing so signs only the commit or tag object itself, which in turn points to other objects containing the actual file data by using their SHA-1 names. A collision in those objects could produce a signature which appears valid, but which points to different data than the signer intended. In such an attack the signer only sees one half of the collision, and the victim sees the other half.

What would a collision attack against Git look like?

The recent attack cannot generate a collision against an existing object. It can only generate a colliding pair from scratch, where the two halves of the pair are similar but contain a small section of carefully-selected random data that differs.

An attack therefore would look something like this:

  1. Generate a colliding pair, where one half looks innocent and the other does something malicious. This is best done with binary files where humans are unlikely to notice the difference between the two halves (the recent attack used PDFs for this purpose).

  2. Convince a project to accept your innocent half, and wait for them to sign a tag or commit that contains it.

  3. Distribute a copy of the repository with the malicious half (either by breaking into a hosting server and replacing the innocent object on disk, or hosting it elsewhere and asking people to verify its integrity based on the signatures). Anybody verifying the signature will think the contents match what the project owners signed.

How is GitHub protecting against collision attacks?

Generating a collision via brute-force is computationally too expensive, and will remain so for the foreseeable future. The recent attack uses special techniques to exploit weaknesses in the SHA-1 algorithm that find a collision in much less time. These techniques leave a pattern in the bytes which can be detected when computing the SHA-1 of either half of a colliding pair.

GitHub.com now performs this detection for each SHA-1 it computes, and aborts the operation if there is evidence that the object is half of a colliding pair. That prevents attackers from using GitHub to convince a project to accept the "innocent" half of their collision, as well as preventing them from hosting the malicious half.

The actual detection code is open-source and was written by Marc Stevens (whose work is the basis of the SHAttered attack) and Dan Shumow. We are grateful for their work on that project.

Are there Git collisions?

Not yet. Git's object names take into account not only the raw bytes of the files, but also some Git-specific header information. The PDFs provided by the SHAttered researchers collide in their raw bytes, but not when added to a Git repository. The same technique could be used to generate a Git object collision, but like the generation of the original SHAttered PDFs, it would require spending hundreds of thousands of dollars in computation.

What future work is there?

Blocking collisions that pass through GitHub is only the first step. We've already been working with the Git project to include the collision detection library upstream. Future versions of Git will be able to detect and reject colliding halves no matter how they reach the developer: fetching from other hosting sites, applying patches, or generating objects from local data.

The Git project is also developing a plan to transition away from SHA-1 to another, more secure hash algorithm, while minimizing the disruption to existing repository data. As that work matures, we plan to support it on GitHub.