Github is well known for its awesome security and has often been first in line to deploy new security mechanism in production. However, some of the work Github has done is not publicly explained so I would like to shine some light on the security implementation at Github.
What I'm most impressed over is that Github is a huge website with millions of users and offer strict security. Many big websites don't want to do this because otherwise they may break compatibility for older clients.
This is a short article showing five things I find awesome with Github's security. Best of all is that we could learn from Github and follow their lead. This article is more a way of describing what I usually do; look at big actors and see how they've implemented their security and figure out why. Personally, this is a great way for learning about web application security defense.
Github's Content Security Policy (CSP) on Github has always been strict and well documented. Github was also one of the first (big) websites that started to use a dynamic CSP to reduce the attack surface.
Dynamic CSP can be very precise and strict, but it can also be the opposite. I would say Github is in the middle of having a perfectly strict CSP and just having a dynamic policy.
For example, Github has the same CSP in all repositories. The
img-src directive whitelist the following:
'self' data: assets-cdn.github.com *.githubusercontent.com [...] and these are not always needed. If we have a repository that has no images we do not need to whitelist for example
*.githubusercontent.com, and yes, there exist examples with other directives as well, not just
One thing Github did very good is having
default-src 'none' on some static resources. This could help mitigate attacks that are directly towards the resource, or in the worst case scenarios where an attacker can upload malicious resources, for example in images.
$ curl -sI https://avatars1.githubusercontent.com/u/1017440 | grep Security Content-Security-Policy: default-src 'none'
Hopefully Github will make their CSP more dynamic in the future and it will be interesting to see how they solve some issues on this front.
Hack for dangling markup
<!-- </textarea> --><!-- '"´ --> is set before all forms that includes a token. This is a smart way of protecting the token when an attacker can extract HTML.
I've written a complete blog post about this here.
As you see in the above screenshot, the secret token is right under the actual comment form. By adding
<!-- </textarea> --><!-- '"´ --> before the form you may stop dangling markup.
Github understands that the
Referrer directive can provide both privacy and security. If we take /pulls (once logged in) as an example we will see
<meta content="origin-when-cross-origin" name="referrer" /> which simply means that only
https://github.com will be sent as a referrer if you click on an link that takes you to another domain other than .*github.com.
As default there're no links that points outside of Github's origin on /pulls, but that may exist in commit messages and in issues. Private repositories are indeed private and their name is stored in the URL. By having a global referrer policy that is
origin-when-cross-origin, the chance of leaking the full URL decreases dramatically. (Thanks to Mathias Bynens for correcting me about this.)
Not only Gihub does this, but it's worth to mention why this is best practice. If we take https://chloe.re. as an example you can actually see that you can visit that domain. The good thing about this is that FQDN are on a separate origin so it probably sounds worse than it really is.
Github redirect correctly:
$ curl -sI github.com./foo/bar?baz | grep ^L Location: https://github.com/foo/bar?baz
FQDN is a valid domain and the browser should treat it like one. Because it is a separate origin there's often no harm not to redirect it, but as best practice you should redirect your FQDN's correctly because it's still your origin.
No CSP for 304's (Not Modified)
As you [maybe] can see in the above video, Github does not send a
Content-Security-Policy header for 304 requests. The policy will still be applied because the whole request is cached, therefore does the server not need to send any
Content-Security-Policy header for 304 requests.
I would like to thank Github for taking security serious and also thank them for being an inspiration for us that has security as a passion. I'm looking forward to seeing more interesting security hacks at Github in the future.