Part 3 of 3 in Git Tales Series
"Some files vanish from sight, but not from memory. Git remembers. So do attackers."
We’ve journeyed deep into the underbelly of modern software development where secrets hide in plain sight, tucked between commits and CI scripts, waiting to be exhumed. In Part 1, we met the careless developer. In Part 2, we followed the breadcrumbs into service accounts, dangling credentials, and quiet privilege escalation in the cloud.
Now, this is the final part of the Git Tales trilogy — and unlike the previous tales, this one breaks apart into three standalone compromises, each unearthed through separate hunts, reported via three different bug bounty programs, and rewarded with high to critical payouts.
Each started differently. Each felt like an accident — a digital whisper. But each time, that whisper led to something massive.
🧨 [ CVE-GIT-001 ]: The Script That Wouldn’t Die
It began like any other passive recon session — checking out a newly public GitHub repository tied to a mid-sized tech company. Nothing looked special on the surface: some README files, a few basic Go services, and tests.
But something odd caught my attention in the commit history, a file named test.sh
had been committed and then deleted. I’d seen this pattern before 😅. And 9 out of 10 times, it's harmless. But that one time? It changes everything.
I pulled the repo and dug deeper. A single commit. Then gone.
But Git’s memory is long.
git checkout <commit-hash>^ -- test.sh
And there it was.
A simple bash script, or so it seemed — containing an HTTP call with a GitHub token hardcoded in plain sight:
#!/bin/bash
curl -H "Authorization: token ghp_abcd1234EXAMPLETOKEN" https://api.github.com/orgs/example-org/repos
I stared at the token. I validated it with trembling fingers 🥲. It wasn’t expired.
curl -H "Authorization: token ghp_abcd1234EXAMPLETOKEN" https://api.github.com/user
200 OK!!! 😅. I was in.
Impact
- Access to 20+ private repos
- Read/write permissions across the org
- Internal CI/CD workflows, API keys, infra configs
- GitHub Actions secrets exposed
I submitted a report through their program, and within hours, triage confirmed its validity. A few days later, the bounty landed 🐞.
🐳 [ CVE-CONTAINER-666 ]: Ghost in the Registry
I wasn’t even looking for containers. Just passively scanning Git objects in a public repo of a private bug bounty program when I found a file named nginx-test-secret.yaml
It was gone from the live branch. Deleted months ago. But as always, Git’s memory outlived the author’s intention.
The file contained base64-encoded ACR credentials. My pulse picked up. Was this real?
I decoded it. Logged in.
docker login myregistry.azurecr.io -u acr-user -p s3cr3tP@ss
Success. The registry door opened.
What It Unlocked
- 80+ private container images
- Secrets in ENV layers (.env, secrets.py)
- Pre-production builds, old tokens, debug configs
- Internal microservices
One image even had Slack bot credentials embedded in its CMD layer. The registry was unscoped. There was no IP filtering. No token rotation. This was a supply chain bomb waiting to go off.
🧱 [ CVE-FUZZ-777 ]: The Git Leak That Bit Back
Sometimes, the real treasures aren’t in public repos or code. They’re in the infrastructure someone forgot existed. They call it "Shadow IT???" 🤔.
While targeting a company’s legacy subdomains, I started a fuzzing job out of curiosity — just to rule out low-hanging fruit. After hours of generic 403s and 404s, I hit on a strange path:
https://old-ci.example.com/test/internal/.git
I download the .git folder to my VPS for analysis and testing.
wget -r -np -nH --cut-dirs=1 -R "index.html*" https://old-ci.example.com/test/internal/.git
I checked the .git/config
file cause I know based on previous experience some devs set creds here 🤫. A full config file, raw and alive with BitBucket credentials present.
[remote "origin"]
url = https://devuser:bb_app_password@bitbucket.org/orgname/infra.git
I paused. Was it real? One command later git clone https://devuser:bb_app_password@bitbucket.org/orgname/infra.git
Boom🤯🤯🤯. Repo cloned. Zero MFA. No IP lock. No alerts.
And this was just the start. The Bitbucket account had access to multiple workspaces (3). In the following hours, performed some critical tests to check the scope of the credentials.
Tests Performed
List All Repositories via Bitbucket API
List Workspaces the user belongs to
Impact
- Access to 60+ internal repos.
- CI/CD secrets, API keys, Terraform configs.
- Slack webhooks, pipeline tokens
- Exposure across 3 different Bitbucket workspaces
This was a critical security hole via infrastructure drift — the kind of bug you only catch by digging where no one else looks anymore.
🧠 Lessons from the Fallout
This breach wasn’t theoretical. Every piece of it mirrors real-world incidents that have happened — sometimes quietly, sometimes splashed across news headlines.
🔐 What should have been done?
- Use least-privilege tokens. Never commit a token with org-wide access. Or just never commit any secrets...
- Secrets detection in CI using tools like Gitleaks, or GitHub's native secret scanning.
- Use managed identities - Especially for container registries and pipelines. No passwords in YAML.
- App passwords ≠ secure APIs. Especially in Bitbucket, where app passwords are commonly over-scoped and under-rotated.
- Monitor audit logs. Both GitHub and Bitbucket offer event logs — but too few organizations actively monitor them.
🔚 The Tale Ends, But the Threat Lingers
The Git Tale wasn’t about zero days or advanced persistent threats. It was about something more dangerous, misplaced trust and developer convenience turned blind spot.
As we close this series, remember:
"Every secret you commit lives forever — unless you treat it like the threat it is."
Your containers aren’t safe just because they’re in a private registry. Your GitHub isn’t secure just because it’s behind SSO. Your Bitbucket isn't safe because it’s split into "separate" workspaces.
Attackers don’t care about your silos. They care about your secrets — and Git will gladly index them for the world to see.
👣 What’s Next?
That’s the end of the Git Tales Series — but just the beginning of a broader journey.
Stay tuned for my next series: “*A bug represents something bigger *” — where we dive into the mind of a hacker or bug bounty hunter.
Until then, guard your Git, rotate your keys, and never trust a silent repo.
Top comments (0)