Almost Found a Github Security Hole
Recently, I was working through a class on github and almost found a way to break the security protocols and write to a repo that belongs to someone else.
In the course, the instructor shows people how to fork his repository and then shows what it looks like when he deletes a file from it.
The thing is, I do not own that repo so I am not allowed to do that myself. I wanted the full experience, so I planned to use my own github as well as a test account that I created. I forked his repo to my account, then my test account forked it again. This way, I would have write access to both an upstream and a downstream repository, just like the instructor did.
The instructor began the lecture by forking his own repository and using git clone
to create a workspace on his computer. Then, he goes to github.com and removes a file from that project.
I do the same, but by forking his repository, then switching users and forking again. I also use git clone
and have no issues doing that.
Next, I decide to add a new file to the repository, instead of deleting one. Either way will create a new commit, so it does not make any difference.
I was able to write the new file (named upstream.txt
) into my repository, as expected. See the screenshot below.
From this point, I click on the link 1 commit ahead
and GitHub compares my repo with the instructor’s repo. See the next screenshot.
From this point, I click on the link Create upstream.txt
to see the commit information and I get a surprise! It seems that GitHub has allowed me to write my file into the repository that I do not own! I was even able to write a comment on that page, as well.
The URL it linked to showed that it is his repo:
https://github.com/bstashchuk/JavaScript-Bible-ES6/commit/f3527880071d4c857fcb5c0c089264ae28a2eda8
My commit got in his repo somehow?
The reason this happened is that GitHub forks all share the same storage on the backend. This lets them save storage space, because when a repository is forked, they do not have to duplicate all of the files.
The yellow warning message displayed hints at the reason:
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
As a consequence, I was able to create a commit object with hash f3527880071d4c857fcb5c0c089264ae28a2eda8
and by adding it into my fork, it went into the common storage area that all forks share.
If I manually edit the URL to have my own user ID, then all is well.
https://github.com/kpanko/JavaScript-Bible-ES6/commit/f3527880071d4c857fcb5c0c089264ae28a2eda8
My commit is actually in my repo where it belongs
I verified that was not actually in the bstashchuk
version by running this:
1
2
3
4
$ git ls-remote https://github.com/kpanko/JavaScript-Bible-ES6.git | grep f352788
f3527880071d4c857fcb5c0c089264ae28a2eda8 HEAD
f3527880071d4c857fcb5c0c089264ae28a2eda8 refs/heads/master
$ git ls-remote https://github.com/bstashchuk/JavaScript-Bible-ES6.git | grep f352788
The commit does not exist in that version; only in mine.
It was a quirk of the way that GitHub works, not a security flaw. Phew!