The sky above the data centre was the colour of split neon, hazel mingled with acid-green hues, modem lights flickering like warning beacons. I tasted ozone under my tongue, the hum of fans and switches a low bass line in this cathedral of silicon. Somewhere behind these vaults of racks, secret fragments of code drifted like spectral motes, API keys, private SSH keys, forgotten credentials, tokens dangling in the shadows. The hunt had begun. I inhaled the stale air heavy with recycled cooling, fingers itching with the thrill of digital trespass, senses sharpened by the promise of dangerous knowledge.
Inside this network I moved like a phantom, crawling through subnets, skirting firewalls, probing open ports. I wore VPNs like armour, proxies as false skin. Packets coursed through fibre with sacred purpose. I saw patterns in TLS handshakes, in spurious HTTP headers, in misconfigured .git directories exposed to the public. Every misstep by an administrator was a shimmering thread, every misconfiguration a doorway. I felt alive in this underworld of secrets.
Finding Secrets, the GitHub Treasure-Hunt
The purpose of this post is to guide you through how to uncover secret leakage via GitHub repositories, misconfigurations, and shadowed artefacts. You must only practise this inside environments you own, or where you have explicit written permission. What follows can be powerful in defenders’ hands, reckless in others.
Section 1: Reconnaissance – map first, strike second
-
Identify your target scope
- Determine the GitHub organisations, users, or repos you are authorised to assess.
- List domains owned by your organisation. Use tools likewhois, DNS bruteforcers.
- Example:domain.com,sub1.domain.com,service.domain.com. -
Crawl GitHub for secrets
- Use GitHub Search API (or web UI) to find exposed keys. Terms to search:apikey,password,secret,token,ssh-rsa,BEGIN PRIVATE KEY.
- Search in commits, issues, pull requests. Secrets often persisted in commit history even if removed.
- Tool suggestion:truffleHog,git-secrets, or custom grep + regex. -
Monitor for shadowed repos
- Repositories may get renamed, archived, left private, then accidentally re-exposed.
- List organisation repos and check their visibility. GitHub API:GET /orgs/:org/reposflagprivate/public.
- UseghCLI:
bash
gh api orgs/myorg/repos --jq '.[] | {name, private}'
- Check .git directories exposed on web servers
- Often misconfigurations allow.gitfolder to be accessible via HTTP. Download.git/indexor.git/HEADto reconstruct history.
- Trycurl http://target/.git/HEAD. If it returnsref: refs/heads/masteror similar, misconfiguration exist.
Section 2: Tooling and code – how to script the hunt
Warning: The following code snippets may be considered offensive, risky, or potentially malicious. Use them only in controlled, legal, and authorised environments. Misuse may violate policy or law.
A. Bash / grep / Git history scrubbing
bash
# Download the repo
git clone https://github.com/myorg/myrepo.git
cd myrepo
# Search commit history for secrets
git rev-list --all | while read commit; do
git grep -I -n -C2 "apikey\|password\|secret\|ssh-rsa" $commit
done
This scans every commit for keywords. Edge case: large repo with binary files, this will be slow and memory heavy. Use --no-filter, exclude certain paths.
B. Python script using GitHub API and regex
python
import re
import requests
GITHUB_TOKEN = "ghp_XXXXX" # NEVER hardcode in production
headers = {"Authorization": f"token {GITHUB_TOKEN}"}
org = "myorg"
page = 1
pattern = re.compile(r'(?:AKIA|SECRET|TOKEN|ssh-rsa|BEGIN RSA PRIVATE KEY)', re.IGNORECASE)
while True:
resp = requests.get(f'https://api.github.com/orgs/{org}/repos?page={page}', headers=headers)
repos = resp.json()
if not repos:
break
for repo in repos:
contents_resp = requests.get(repo['contents_url'].replace('{+path}', ''), headers=headers)
for item in contents_resp.json():
if item['type'] == 'file':
file_resp = requests.get(item['download_url'], headers=headers)
if pattern.search(file_resp.text):
print(f"Possible secret in {repo['name']}/{item['path']}")
page += 1
Edge cases: rate limits, large files, false positives (comments or example config). Solve by rate handling, whitelist extensions (.md,.txt), manually vet findings.
C. Detecting exposed .git folder
bash
curl -I http://target/.git/config
curl -I http://target/.git/HEAD
If HTTP status 200 for either, serious misconfiguration. Then maybe mirror .git folder content with wget --mirror. Use with care; may violate policy.
Section 3: Workflow – threat modelling and response
-
Threat modelling
- List assets potentially exposed: SSH private keys, AWS secrets, database credentials.
- Determine attack paths via exposed secrets: lateral movement, privilege escalation, breach. -
Prioritisation
- Secrets with high privilege access (production systems, admin APIs) are more urgent.
- Credentials stored in plaintext in code get higher severity than those encrypted or obfuscated. -
Validation
- For any secret found, try to verify (in safe environment) whether it works, or it is dummy data. Never brute force or mis-use.
- Check with owner if secret is still valid. -
Remediation
- Rotate exposed secrets immediately.
- Remove the secret from repo history (e.g.git filter-branchorgit filter-repo).
- Ensure.gitdirectories are not web-accessible (via web server configuration).
- Add secrets to vaults or secrets managers (Hashicorp Vault, AWS Secrets Manager).
- Establish pre-commit hooks, scanning at CI/CD.
Section 4: Edge cases, camouflage, and ghost secrets
- Camouflaged keys: Secrets hidden within other file types (images via steganography, binaries, less-obvious extensions). Use entropy checks or tools like
binwalk. - Encrypted secrets: Files that are encrypted but keys stored elsewhere. Danger when the decryption key is in repo. Check for
.enc,.gpg, and search for decryption scripts. - Third-party dependencies: Open source packages or submodules may leak secrets. Scan submodules and dependencies too.
- Token reuse and credential stuffing: Even a low-privileged token may provide pivot. Map permissions. Check scopes of OAuth tokens, AWS IAM policies, GitHub App permissions.
Mini Checklists
| Phase | What to check |
|---|---|
| Reconnaissance | GitHub org list, repo visibility, domain-repo mappings |
| Code scan | Keywords, history, regex alerts, .git exposures |
| Validation | Confirm secret works or is planned rotation, owner notified |
| Remediation | Remove, rotate, lock down access, implement CI checks |
Quick Lab You Can Try Tonight
- Setup a test GitHub organisation or repo.
- Create a file
config.txtcontaining a dummy AWS secret and SSH private key block. Commit it. - Expose
.gitfolder by serving the repo via a simple HTTP server with no directory restrictions. - Use the Bash script to find the dummy secret.
- Use the curl commands to check
.git/configand.git/HEAD. - Remove the secret via
git filter-repoorgit filter-branch. Rotate dummy credentials in your test cloud.
Actionable Takeaways
- Even small oversights like a public
.gitfolder expose the entire project history. - Secrets linger long after removal unless scrubbed properly.
- Automated scanning (CI/CD, pre-commit hooks) and periodic manual audits are essential.
- Permissions and roles of tokens matter as much as the secret itself.
Sharpen Your Skills: GitHub Secrets Treasure Hunt
Aim
You will learn how to locate, understand and mitigate exposed secrets (API keys, tokens, credentials) in GitHub repositories by using effective tools, methods and best practice workflows.
Learning Outcomes
By the end of this guide you will be able to:
- Recognise common types of secrets and where they typically occur in code.
- Use tools like Gitleaks, detect-secrets and shhgit to discover secrets in active codebases and commit history.
- Write regular expressions and use entropy measures to identify hard-coded credentials.
- Integrate secret scanning into your development workflow (pre-commit hooks / CI).
- Prioritise secret removal by risk level and implement secure storage for secrets going forward.
Prerequisites
- Basic knowledge of Git and GitHub (cloning, commits, branches).
- Familiarity with bash shell or PowerShell, and Python if modifying or writing scripts.
- Access to a code repository to test on (public or private).
- Installation Rights to add pre-commit hooks and CI workflows (e.g. GitHub Actions).
- Tools installed: Git, Python, optional tools such as Gitleaks, detect-secrets, shhgit.
Step-by-Step Guide to Finding Secrets
1. Identify what counts as a secret
- Examples include: API keys, database strings, SSH/private keys, cloud credentials, tokens embedded in code. GitHub defines secrets this way and warns that exposed secrets compromise systems. (docs.github.com)
- Use GitHub’s secret scanning to detect known patterns in your repositories and alerts administrators when secrets are found. (docs.github.com)
2. Scan existing codebase and commit history with detect-secrets
bash
pip install detect-secrets
cd path/to/your/repo
detect-secrets scan --all-files --baseline .secrets.baseline
--all-filesforces scan including non-source files.- Store a baseline file to track previously known secrets and focus on new leaks. (github.com)
3. Use Gitleaks to detect secrets in streams or archives
bash
# Scan a local directory
gitleaks detect --source=. --report-path findings.json
# Use in Docker
docker run -v "$(pwd)":/path gitleaks/gitleaks:latest detect --source=/path
- Captures regex-based detections, high entropy strings, and secrets hidden inside archives. (github.com)
4. Run shhgit for live detection across GitHub, GitLab or Bitbucket
bash
shhgit --search-query "AWS_ACCESS_KEY_ID=AKIA" --local path/to/code
- Supports public API mode or local scanning mode. Offers signature-based detection for many secret types. (github.com)
5. Add pre-commit or CI pipeline checks
- Using detect-secrets:
yaml
# .pre-commit-config.yaml
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.0.0
hooks:
- id: detect-secrets
- Or using Gitleaks action: run scans on pull requests and pushes to prevent secret leaks before merge. (github.com)
6. Prioritise removal based on risk and context
- Assess severity: Is the key active? Which service does it access? Does it grant wide permissions?
- Tools like RiskHarvester assign risk scores to exposed secrets combining asset value and attack ease. (arxiv.org)
7. Mitigate discovered secrets
- Revoke or rotate compromised credentials.
- Move secrets into secure vaults or environment variables, remove them from source code.
- Update .gitignore so files containing secrets aren’t accidentally committed.
- Educate team on security best practice.
Actionable Insights
- Begin with a full scan of your repository and commit history using detect-secrets or Gitleaks to ensure nothing has been overlooked.
- Tune false positive thresholds (entropy, keywords) so your detection tools are useful, not noisy.
- Automate secret scanning in pull requests to enforce code hygiene.
- Maintain a secrets baseline or allow-list so you can defer addressing low risk yet known issues without losing visibility.
- Log and monitor secret exposure alerts using GitHub’s secret scanning feature, particularly for public repos and organisation-owned ones. (docs.github.com)
Use these steps to sharpen your ability to find, remediate, and prevent secret leaks in GitHub repositories.
I descended finally through the stacks of routers and firewalls, tracers burning like small suns behind every log entry, the flicker of invalid authentication attempts like neuron‐fires. My scripts cracked open history, grep spat out keys, curl exposed raw HEADs, and in that neon aftermath I tasted victory and shame in equal measure. The network pulsed around me with secrets both lost and found, the tools of Python regexp, Bash loops, HTTP probes dancing amidst TLS certificates and token scopes, reminding me that vigilance is the only true firewall, curiosity the fiercest VPN.