Saturday, June 14, 2025

How I Earned a $617 Bounty from GitHub

 

Not Essential (Intro)

Hey folks, it's been a while since my last blog post. To be honest, i suffer from a serious case of procrastination when it comes to writing, and I have huge respect for everyone who does it consistently. I've decided that instead of not sharing my findings at all, it would be better to switch things up. So, this blog is about to become more of a vlog. Expect more proof-of-concept (PoC) videos and a bit less text. Please bear with me as I try out this new format.

This first post is special. It covers my first validated bug on HackerOne ever since,i temporarily stopped hacking on bugcrowd.

The Vulnerability Explained

The core issue I discovered was a two-part authorization bypass within the GitHub Rulesets feature, stemming from the application improperly trusting a client-side check to gate sensitive actions. By intercepting the /sessions/in_sudo endpoint and using a match-and-replace rule to change the API's response from false to true, I could trick the front-end into believing my session had elevated sudo privileges. This allowed me to perform two critical actions without the required password re-authentication: first, creating a new ruleset (Report #3075134), and second, deleting an existing one (Report #3094044). Because both vulnerabilities relied on the same flawed validation mechanism, they were essentially two sides of the same coin, and the server-side fix for the first report ultimately resolved both.

Why This Worked: The Client-Side Trust Issue

The vulnerability existed because of a classic security anti-pattern: the back-end trusted the client's state. Think of it like a security checkpoint with two guards. The first guard (the front-end UI) is supposed to ask for your password. It determines whether to do this by asking a separate endpoint, /sessions/in_sudo, "Is this person already in sudo mode?" When that endpoint returned false, the UI knew it had to show the password prompt. However, by intercepting the response and changing it to true, I essentially told the first guard, "Don't worry, I'm already cleared." The crucial mistake was that the second guard (the back-end API that actually creates or deletes the ruleset) never performed its own check. It trusted that the first guard had done its job and blindly accepted the request. The single source of truth for security must always be the server; in this case, the sensitive action was gated by a UI element that could be manipulated, rather than by a strict, non-negotiable server-side permission check.

The Proof of Concept (PoC) Video

Talk is cheap, so here's the video. It demonstrates exactly how this vulnerability worked in practice, from intercepting the request to successfully creating and deleting a ruleset without the proper authorization.

 

 

 

----------------------------------------------------------------------------

Thanks For Coming Here!!

I hope this was interesting and a good look into both the technical and human side of the issue. I'm excited to share more in this new format soon.

Before I sign off, I need to give a few important shout-outs. A huge thanks to the Critical Thinking team for their excellent video on client-side match and replace techniques. A big thank you to the teams at HackerOne and GitHub for running an awesome bug bounty program and for graciously allowing me to disclose this finding, even as a low-severity vulnerability. Finally, a special shout-out to dev.ai  who thinks it's chatgpt for  some weird reason for being a fantastic brainstorming partner and helping me structure this post to bring it all together.

 

 

Byeeeeee!!!!!!!!!!!! 

How I Earned a $617 Bounty from GitHub

  Not Essential (Intro) Hey folks, it's been a while since my last blog post. To be honest, i suffer from a serious case of procrasti...