Accidentally a hacker
Tags: beginners, security, github
Published: 2020-06-26 10:55:21

Around the beginning of February 2020, GitHub Security updated their [public security disclosures](https://bounty.github.com/bounty-hunters.html) and [hacker leaderboard](https://bounty.github.com/index.html), and this happened:

![GitHub Security Leaderboards with Vlad Ionescu on the ninth position out of ten people](https://dev-to-uploads.s3.amazonaws.com/i/jb20rltsjc4xml0aha9k.png)

Previously, on October 7, 2019, something popped up on [HackerOne](https://www.hackerone.com):

![A 10000 $ bounty awarded to Vlad Ionescu on HackerOne for a GitHub security report](https://dev-to-uploads.s3.amazonaws.com/i/mw6vg0hyqnwideov6ofj.png)

This is the story of how it all came to be. Unlikely to ever have a sequel.

------


## Vlad likes pretty

Something most people on the internet don't know about me is that I like pretty stuff. Be it a [whiskey pipette](https://www.eischcrystalglass.com/shop/gentleman-whiskey-pipette-gold/), a [lovely painting](https://afremov.com/passion.html), many [dog thoughts](https://twitter.com/dog_feelings), a [ferocious lover](https://www.youtube.com/watch?v=dQw4w9WgXcQ) — it does not matter. I like pretty!

Although I generally have excellent impulse control[1], pretty is pretty and I want pretty. I want to enjoy pretty. Savor pretty. Surprisingly often, this puts me in weird situations — like accidentally hacking GitHub.

## CircleCI is not pretty

[CircleCI](https://circleci.com) is a hosted build service. It can build or compile code to ensure there are no build errors, it can run tests to ensure the correct thing happens, it can do whatever you want it to do!

But CircleCI is not pretty. For some cruel reason, CircleCI forces people to log in to their UI to get to the test output. Oh, a test failed? Spend 3 minutes following redirects and logging into things. Only then you get to see why the test failed.

The typical workflow looks like this:

- do some work
- send work to GitHub
- CircleCI is notified and starts building and testing the code
- notification is received from GitHub and/or CircleCI
- go to GitHub, see that the "_Test X_" step failed
- click "_Details Test X_"
- click "_See more in CircleCI_"
- new tab opens
- click "_Log In_"
- go through the login process
- finally, see how the test failed

WHY?! I don't understand why CircleCI even has [a GitHub integration](https://github.com/marketplace/circleci). Why not have the output **right there** on GitHub? Why does CircleCI insist on adding another step to the whole process?

It's not even a limitation on the GitHub side: [Brigade](https://brigade.sh) can, and does, [precisely that](https://github.com/brigadecore/brigade/pull/914/checks?check_run_id=130703731)!

I really do not like the whole user experience around the CircleCI integration with GitHub. It was, and it still is, a constant source of annoyance for me. I mean look at it:

![An image comparing CircleCI in GitHub( three builds, 1 failed, and a link below with 'See more details on CircleCI' versus a Brigade test run with the output right there](https://dev-to-uploads.s3.amazonaws.com/i/xew07t0fi3pqdrumb4tk.png)

## GitHub Actions are pretty

In August 2019, it happened: I finally got access to the [GitHub Actions Beta](https://techcrunch.com/2018/10/16/github-launches-actions-its-workflow-automation-tool/)! A day I was very much looking forward to.

I am working on a continuous challenge to be less cranky, and CircleCI was making me cranky. This was a chance for me to be happier!

[GitHub Actions](https://github.com/features/actions) are similar to CircleCI: they can build code, they can test code, they can do whatever you want them to do!

Even more, GitHub Actions can answer to more than just new code: they can run when a comment is posted, or when a change is approved! This flexibility empowers people to build even more amazing workflows.

I **immediately** started playing around with GitHub Actions. I **loved** everything about them — they were so flexible. More importantly, the output is right there. On the same page! Look how gorgeous they are:

![An image showing very clear and pretty logs from GitHub Actions](https://dev-to-uploads.s3.amazonaws.com/i/md6c1eqrpsf7nln87bj8.png)


Everything was nice in the world. For a couple days.

## GitHub Actions user experience is not pretty

GitHub Actions were unacceptably slow due to a lack of caching, and don't even get me started on the whole slew of unexpected and random limitations.

You think GitHub Actions can answer to say a comment being posted on a Pull Request, but then surprise! They can indeed run on a comment post, but you don't actually have access to the code in that Pull Request.

I started working with GitHub Actions more and more, and I started even creating some actions. It was not pretty, but it was prettier than the CircleCI alternative.

I was doing a lot of [Terraform](https://www.terraform.io) at that time, and I really wanted warnings from [tflint](https://github.com/terraform-linters/tflint/) on Pull Requests. Output on the separate _Checks_ tab was not enough anymore — I wanted it in the _Conversations_ tab. That is where I spend my time, so that is where everything relevant should be. I don't want to even have to press one button.

## GitHub Actions are pretty with reviewdog

I ended up discovering the lovely [reviewdog](https://github.com/reviewdog/reviewdog): it takes the output from any tool and sends it to GitHub!

Want the output as a _Check annotation_? It can do that. Want the output as a _Review comment_? It can do that.

Look how pretty it is:

![Reviewdog posting a comment on a Pull Request with a golint error](https://dev-to-uploads.s3.amazonaws.com/i/39lheymw3l5is0r87dqm.png)

It was love at first sight! I started working more and more with reviewdog, and I even ended up writing [a reviewdog tflint GitHub Action](https://github.com/reviewdog/action-tflint)!

Life was good again!

## GitHub Actions are not pretty if it has unexpected limitations

Now I get notified that things are wrong, and in the right place. But wouldn't auto-fixes be even prettier? Not fully automatic, but something like "_click a button and it's fixed_".

Since I want pretty, I started working on it! I imagined something along these lines:

- GitHub Actions sees that code formatting is wrong
- reviewdog posts a comment letting me know
- when the time is right, I comment `pls fix`
- automated fixes just appear

GitHub Actions at that time were very... particular about how they downloaded the code and what version of the code was downloaded. For the life of me, I could not get an auto-fix workflow to do what I wanted.

## GitHub Actions are pretty with auto-fixes

After about a week of perusing the ~~incomplete~~ very beta documentation, I figured it out!

If I post a comment on the review screen and have the auto-fixer GitHub Action respond to the `pull_request_review` event, it all works! WOOOO! The right code is downloaded, the fixes are pushed back, everything works!

Life was so pretty! It was an exemplary workflow, and it made life so much easier.

## GitHub Actions are not pretty if it leaks secrets

I was so proud of the thing I built. I was even [telling people about it](https://github.com/terraform-aws-modules/terraform-aws-eks/pull/541) and [insisting they use it](https://github.com/reviewdog/action-tflint/issues/2#issuecomment-536319167) because it is a better user experience.

In one of the chats, [it was pointed out to me](https://github.com/reviewdog/action-tflint/issues/2#issuecomment-536320327) that I was kind of breaking the security of GitHub Actions.

In my mind it was just "_beware, you need to set this thing for this to work_", not "_please create a secret so I can steal it_".

I have access to a surprising amount of GitHub Organizations and GitHub Teams, so I went forth and tested if I was actually breaking the Secret protection.

In 10 minutes I had confirmed that I was indeed able to steal any secret for any public GitHub repository, without any user involvement.

Oops.

## Submitting the report

Allow me to set the scene.

It is late in the evening on September 29. I am on my couch with my laptop and a glass of [Lupi](https://www.gitana.md/en/shop/reserve/lupi-2/), a lovely blend of red wines. Rather inebriated, but happy and content. Doing stuff on GitHub.

I panicked a bit. I allegedly found a security issue. I am also drunk, so I might be wrong. But I could be right. But I am a dum-dum and GitHub people are smarter than me, so there is no way. But what if?

Fuck. I panicked some more.

I had to report it — even if there was a small chance of it being real, there was a risk. I never had any issues or reservations about looking dumb: that's how you learn!

I imagined I would send an email to something like `security@github.com`. Looking into it, I saw that GitHub has an [open process on how to report security issues](https://help.github.com/en/github/site-policy/responsible-disclosure-of-security-vulnerabilities): they have a [HackerOne](https://www.hackerone.com) account. HackerOne handles the process and GitHub responds. Nice!

I quickly created an account with HackerOne, hoping that a 2-minute-old-account will be allowed to send a report. Surprisingly, they allow that. Nice!

Drunkenly, I wrote a report and submitted it. For your pleasure, here it is in all its glory:

<!-- markdownlint-disable MD034 -->
> **Description**:
>
> Unsure how much of a security issue this is but better safe than sorry. This is my first report ever so I have no idea what I am doing. Apologies if I am wrong.
>
> GitHub Actions for the pull_request_review event run in the base repo not in the fork. But a fork can change the code for the action to leak secrets. No input is needed.
>
> This was discussed a bit on https://github.com/reviewdog/action-tflint/issues/2 where I was urged to report it.
>
> **Steps To Reproduce**:
>
> See https://github.com/org-name-redacted/repo-for-fork-testing/pull/9 with the https://github.com/org-name-redacted/repo-for-fork-testing/commit/2dc3d01c3f342d722ca0a0b0543901a15de7fe16/checks check, the Test step. I base64 encoded the secrets to get around the secret hiding thing.
>
> 1. Have a public repository with GitHub Actions access and some Secrets set for the repo
> 2. Fork the repo to an account
> 3. Add an action that runs for pull_request_review that tries to get the value of a secret
> 4. Create PR to the public repository
> 5. Leave a review comment on the created PR
> 6. Go to the Actions tab where the action ran and secrets values can be found
>
> This does require knowing the secrets name, but I guess a brute force attack searching for secrets names is not improbable.
>
> Again, apologies if Actions is out of scope/ this issue is known.
>
> **Impact**
>
> Leaking of secrets( whose names are known) for any public repository with GitHub Actions enabled.
<!-- markdownlint-disable MD034 -->

I woke up the next day. A ridiculously sunny Monday. I thought about it some more, and I updated my initial report.

I remember it vividly: I was in an Uber on my way to a client onsite, and I was sitting in the back trying to write a "_serious_" and "_adult_" report:

> Hi,
>
> I don't see a way to edit this but I'd like to raise this to Critical. I am still new and confused, but being able to leak any secret from GitHub Actions seems huge to me.
>
> While Actions are still in preview, multiple projects use them already. This exploit has a huge impact for GitHub Actions and for any org using Actions:
>
> - [Homebrew can be totally taken over](https://github.com/Homebrew/homebrew-core/blob/e9b3867c54009a63d396e6642ddeaf0063152205/.github/workflows/generate_formulae.brew.sh_data.yml#L17)
>
> - [Ruby's AWS Keys are easily retrievable](https://github.com/ruby/ruby/blob/8ba48c1b8509bc52c2fc1f020990c8a3a8eca2c9/.github/workflows/draft-release.yml#L80)
>
> Pretty much every secret on GitHub can be retrieved in less than 5 minutes, with no action required from the person being attacked. A very easy way to find names [is to search for secrets in .github/worrkflows across all GiHub](https://github.com/search?q=secrets+path%3A.github%2Fworkflows). Once a name is found the repo is forked, a PR is created back with the following code, a comment is left on the PR, and in less than 1 minute the secrets are out:
>
> ```yml
> name: Leak
>
> on: [pull_request_review]
>
> jobs:
>   leak:
>     name: Leak GitHub Seecrets
>     runs-on: ubuntu-latest
>     steps:
>       - name: Leak the secre
>         run: |
>           echo $VALUE | base64
>         env:
>           VALUE: ${{ secrets.SECRET_NAME_WHICH_IS_EASY_TO_GET }}
> ```
>
> Please treat this with the highest priority.
>
> Thank you,
>
> Vlad Ionescu

It had a typo and all that, but it was a better report.

## GitHub Bounties are pretty

GitHub, to their credit, responded super-fast to the report. Keeping in mind that times are local to Bucharest and the US is 10-ish hours behind, the timeline looks like this:

- Dead-of-the-night Sunday, September 29: initial report
- Early Monday, September 30: updated report
- Late Monday, September 30: report triaged and GitHub started working on it
- October 7: 10.000 $ bounty awarded for the bug report[2] [3]
- October 18: lifetime GitHub Pro subscription awarded, formal invitation into [@GitHubBounty organization](https://github.com/GitHubBounty)

## GitHub Bounties spam is weird

As soon as GitHub awarded the bounty, their HackerOne page was updated and showed that _"Vlad Ionescu reported something secret and got 10 grand from GitHub"_. That brought more attention to me than I would've liked to. It was a bit overwhelming.

I started getting a bunch of messages asking me for details about the vulnerability. I started getting a lot of messages asking me if I want to pair on researching bugs.

On the one hand, that is very spammy. On the other hand, awww, people hack together and collaborate and that seems nice? I have doubts about how nice it actually is.

## Conclusion

The fact that a random human with zero experience can just create an account on HackerOne and report a security issue to a major company is fantastic. And they take these reports seriously! And give out rewards!

Major props to [HackerOne](https://hackerone.com) and the [GitHub Security Team](https://github.com/security/team) for all this! They managed to create an outstanding process, and they stick to it.

Also, I can now put _Security Researcher_ on my resume! Ahem, it's a resume; I have to sell myself. "_Established myself as part of the [top 0.3 percent of hackers](https://duo.com/decipher/taking-hype-out-of-bug-bounty-programs)_".

--- 

[1]: Shhhhhhhh. I really do!
[2]: I, of course, tried negotiating for a higher bounty. Well, "_asking_" cannot really be called negotiating.
[3]: The reward was split with the person that suggested reporting the issue to GitHub.