October 14, 2026
The Company’s Secrets Are on GitHub, and Nobody Noticed Yet
Exposed keys, old code, and deleted commits: how hunters find what developers never meant to share

By Yamini Yadav_369
10 min read
Part 5 of 7 in Recon From Zero: The 7 Part Hunter's Map
A developer I once read about pushed a file to a public repository at eleven at night, fixed a bug, and pushed again five minutes later to remove it. In his head, the mistake was gone. He deleted the line, the file looked clean, and he moved on to the next task.
But GitHub does not forget like that. It keeps history. Every version of every file stays in the project forever, unless someone goes through the slow, deliberate process of rewriting that history. The line he deleted, a line that happened to contain a real password, was still sitting there, one click away from anyone who knew to look at the file's past instead of its present.
This is the strange thing about leak hunting. You are not looking for a hole in a wall. You are looking at a diary that developers write every day of their working lives, in public, and mostly without thinking about what they are recording. Commit messages, old branches, test files, personal projects: all of it sits in the open, searchable by anyone.
I want to be honest about something before we go further. This part can feel like the most exciting one in the whole series, and it is also the one where beginners get into trouble fastest, because the line between finding a secret and misusing a secret is thin and very serious. We will spend real time on that line.
What you will learn
By the end of this part, you will know how developers accidentally leak secrets and why it keeps happening even at careful companies. You will be able to search GitHub properly, read commit history for things that were removed, and recognize real working credentials instead of placeholder text. You will also know exactly what to do, and not do, the moment you find one.
Why leaks happen even at careful companies
Think about how often you copy and paste something while rushing. A developer working on a live problem at midnight is not thinking about security. He is thinking about the error in front of him. He copies a real database password into a config file to test something locally, fixes the bug, and pushes the whole folder because it was faster than sorting out what to exclude.
Companies try to prevent this with a file called.gitignore, which tells the system which files to never track, like local settings. But .gitignore only works going forward, and only if someone remembers to use it before the first commit. If a secret made it into history even once, deleting the file later does not erase that earlier moment.
There is also a human pattern worth knowing. People leak secrets most often in three situations: when they are learning and following a tutorial that uses a real key by mistake, when they are debugging and paste real values to save time, and when they fork a company project to make a personal change and carry its secrets into their own public account without realizing it.
Searching GitHub like you mean it
GitHub's own search bar supports operators similar to Google's, though the exact syntax has changed a few times over the years, so check GitHub's search documentation page before you rely on any specific operator. As of now, useful patterns include limiting by organization, by file name, and by extension.
A few real searches to try, replacing example with your actual target:
org:example-company password
org:example-company "api_key"
filename:.env
filename:wp-config.php
extension:pem
extension:json "private_key"org:example-company password
org:example-company "api_key"
filename:.env
filename:wp-config.php
extension:pem
extension:json "private_key"Reading these: org: narrows results to repositories under a company's GitHub organization, if they have one, which you can find on their GitHub profile page. filename: searches for files with an exact name, and .env files are a very common place for secrets because many frameworks load settings from them. extension: searches by file type, and .pem files often hold private cryptographic keys.
A second, very different approach is searching outside the company's own organization. Developers leak company secrets from their personal accounts constantly. Search the company's internal domain name, a distinctive internal hostname, or a specific internal service name, combined with words like password, secret, token or config.
"internal.example.com" password
"example-company" "aws_secret_access_key""internal.example.com" password
"example-company" "aws_secret_access_key"What the result means: GitHub's own code search has had limits on how deep it searches and how fresh results are, and this changes over time, so if your first search feels thin, try the dedicated code search page rather than the general search bar, and try narrower, more specific phrases.
Specialist tools built for exactly this
Because manual searching misses a lot, dedicated tools exist. These tools and their features change often, so check each project's page for current usage before you run anything.
- TruffleHog scans repositories (or even your own clipboard or local files) for patterns that look like real secrets, such as AWS keys, and many versions can verify whether a found key is still active, which saves huge amounts of guessing.
- Gitleaks does a similar job with a large built in list of patterns for different secret types, and works well scanning one repository at a time.
- GitHub Dorks is not a single tool but a well known list of useful search terms, maintained by various people on GitHub, worth a quick search to see the current version.
A typical run, after installing TruffleHog:
trufflehog github --org=example-companytrufflehog github --org=example-companyThis tells the tool to scan every public repository under that organization's account. Reading the output: each finding usually shows the file, the line, the type of secret detected, and, in newer versions, whether the tool could confirm the secret still works by testing it against the real service in a safe, read only way. A result marked verified deserves your full attention. A result marked unverified might be an old key that no longer works, or might be a placeholder from a tutorial, so you check by hand.
Reading history, not just the present
The real skill in this part is understanding that the current file is only the latest page of a long diary. Three places hold the older pages.
Commit history: Every change to a file is a commit, a saved snapshot with a message. On GitHub, open a file and click "History" to see every version. A commit message like "remove hardcoded password" is basically a signpost pointing at exactly the commit before it.
Deleted and old branches: A branch is a separate line of work. Developers sometimes push secrets to a branch, then delete the branch once merged, believing it is gone. Often it is still reachable through GitHub's own search or through tools that look for dangling commits, commits that no longer belong to any visible branch but have not been fully erased from the server yet.
Forks: When someone copies a company's public repository to experiment, their fork is a separate public copy. If the original later removes a secret, older forks may still show it, because each fork is its own frozen history unless the owner updates it.
A small example, labeled as made up but very realistic. A hunter named Oskar was reading the commit history of a public repository owned by a fictional company, Brightleaf Logistics. He noticed a commit titled "oops, remove test key" sitting right after a commit titled "add database connection test." He opened the first commit, the one before the removal, and found a real-looking connection string with a username and password. He did not try to use it. He copied the exact file path and the commit hash, a unique code that identifies that exact snapshot, and included both in his report so the company could find it instantly.
Is it even real? Reading a credential properly
Finding something that looks like a secret is not the same as finding a leak. Tutorials, example files, and test suites are full of fake keys written to look real. Telling them apart is a real skill.
Signs a key is probably fake or a placeholder: it uses obviously fake words like "yourkeyhere", "xxxxxxxx", "example", or "changeme". It appears in a file clearly named example, sample, or template. It matches a publicly known example key that a vendor publishes in its own documentation on purpose, such as Stripe's well-known test keys, which are meant to be public and safe.
Signs a key might be real: it sits in a normal-looking config file alongside other real-seeming settings. It was added, then specifically removed later with a message that suggests urgency. It matches the exact format a real service uses, such as the particular prefix and length AWS access keys follow, rather than an obviously shortened or altered version.
Tools like TruffleHog that can verify a key are valuable here because they remove guesswork. When no verification is possible, treat the key as a strong lead, not a confirmed fact, and say so plainly in your report.
What to do the moment you find a real secret
This is the most important section in this part, more important than any search operator. Finding a working credential puts you at a genuine decision point, and the wrong choice here can turn a great find into a serious legal problem for you.
Do not log in with it: Do not query the database it unlocks. Do not list the files in the storage bucket it opens. Do not run any command using it, not even one that only reads data to "confirm" it works, beyond the kind of safe, limited verification a tool like TruffleHog performs automatically, which checks validity without pulling real data. The moment you use a credential to access systems or data beyond what the program explicitly allows for confirmation, you have likely crossed from research into unauthorized access, even if your intentions were good.
What you do instead: take a screenshot or copy the exact text, note the file, the commit hash and the repository URL, and write a report that states plainly what you found and where, without demonstrating further access. Many programs specifically say in their rules how they want leaked credentials handled, so read that section of the policy before you report. If a program is not clear, lean toward reporting the exposure itself and let the company's own team verify it on infrastructure they control.
A full walkthrough: Brightleaf Logistics
Brightleaf Logistics is fictional, and example.com is a stand in domain. Everything shown is illustrative.
Step 1: Find the organization. I search Brightleaf's name on GitHub and find a public organization called brightleaf-logistics with six public repositories, mostly small internal tools.
Step 2: Search broadly.
org:brightleaf-logistics "aws_secret_access_key"org:brightleaf-logistics "aws_secret_access_key"One result appears, inside a repository called infra-scripts, in a file named deploy.sh.
Step 3: Open the file. The current version of deploy.sh has the value replaced with a placeholder that reads REPLACE_ME. So the present file is clean. This is where most beginners stop, satisfied that there is nothing here.
Step 4: Check history. I click History on that file and see five commits. The third one down is titled "fix typo in deploy script," which is an ordinary sounding message, the kind nobody would suspect. I open it anyway, because the file changed in this commit and I want to see exactly what changed.
Step 5: Read the diff. The commit shows one line removed and one line added. The removed line held what looks like a real AWS secret access key, in the correct format, sitting in plain text before it was replaced with the placeholder in a later commit.
Step 6: Treat it seriously but carefully. I do not run any AWS command with it. I copy the exact commit hash, the file path, and the line number. I take a screenshot of the diff view showing the removed line.
Step 7: Check for more. I run TruffleHog against the whole organization in case other repositories hold something similar.
trufflehog github --org=brightleaf-logisticstrufflehog github --org=brightleaf-logisticsIt finds the same key and marks it in its output as something it could not verify live, because by now the real key may have been rotated. That is fine. The report does not depend on proving the key still works. It depends on showing the company exactly where and how it was exposed.
Step 8: Write the report. I describe the repository, the exact commit, the file and line, what kind of secret it is, and the date range it was exposed based on the commit timestamps. I state clearly that I did not attempt to use the credential. I attach the screenshot.
Mistakes I See Beginners Make
Only checking the current file. The present version is often the cleanest part of the whole history. Fix: always click into history when a file looks like it could hold settings or credentials.
Testing a key to "be sure." This feels responsible but is often the opposite. Fix: use a tool's built in safe verification where it exists, and otherwise report without testing.
Reporting obvious placeholder text as a real leak. This wastes the company's time and your credibility. Fix: learn the signs of fake keys before you report, and say in your own report how confident you are and why.
Forgetting forks and personal accounts. Beginners only check the company's own organization. Fix: search the company's internal names and services across all of GitHub, not just their official account.
Downloading and keeping sensitive data "for the report." Some programs and some laws treat holding onto real exposed data as its own problem. Fix: take only the minimal evidence needed, described above, and do not download or store customer data itself.
Giving up after one search. A single search operator rarely finds everything. Fix: try several angles, the company's org, their internal domain name, specific service names, and dedicated tools, before deciding there is nothing there.
Your practice task for today
Do not search real companies for this practice unless you are doing it under an authorized bug bounty program with GitHub recon explicitly in scope. Instead, use a safe lab approach.
Spend one hour:
Create a small test repository of your own on GitHub. Add a fake config file with an obviously fake-looking key, commit it, then remove it in a later commit.
Practice finding your own removed secret using the History view, so you understand exactly what a real find looks like.
Install Gitleaks or TruffleHog and run it against your own small repository to see what its output looks like.
Read the official documentation page for GitHub's code search to see its current operators.
Write a short practice report describing your fake finding the way you would report a real one: file, commit, line, and what you did not do.
If you can produce that practice report clearly, you understand the whole part.
What comes next
You have now looked at what a company says about itself, where its forgotten servers live, what those servers run, and what its developers have accidentally shared. There is one more place secrets hide in plain sight: the website itself, in folders nobody links to and JavaScript files that quietly list every feature the app can do.
In Part 6, you will learn content discovery: how to find hidden folders, old endpoints, and the secrets buried inside JavaScript files that your browser downloads on every visit. Bring your notebook, your short host list from Part 3, and the tech details from Part 4.
Medium tags: BugBounty, Cybersecurity, EthicalHacking, GitHub, InfoSec
Hashtags: #BugBounty #Cybersecurity #EthicalHacking #GitHub #InfoSec #DataLeak #Pentesting #BugHunter #CyberSecurityForBeginners #AppSec