What Happens When Your GitHub Repository Gets Exposed: A Security Guide for Developers
An accidentally public GitHub repository can expose API keys, database credentials, and source code within minutes — here is what to do immediately if it happens, and how to prevent it.
The moment you realise your repo was public
It happens more often than most developers admit. A repository created as private, accidentally set to public during a settings change or organisation migration. A .env file committed before .gitignore was configured. An API key hardcoded months ago, forgotten, and then the project open-sourced.
The window between exposure and discovery can be minutes. Automated bots continuously scan GitHub for newly public repositories and recently committed secrets, harvesting credentials before the developer has even noticed the mistake.
This guide covers what to do if it happens to you, and how to make sure it does not happen again.
What gets exposed in a typical repository leak
The most damaging exposures from a public repository:
API keys and tokens. AWS access keys, Stripe secret keys, Twilio auth tokens, GitHub personal access tokens, Anthropic API keys, Slack webhooks — any service credential committed to the repository is now in the hands of whoever finds it first.
Database connection strings. A DATABASE_URL with username, password, host, and database name gives direct access to your production database. Combined with an exposed port (also findable via Shodan), this is catastrophic.
Private keys and certificates. SSH private keys, TLS private keys, or code signing certificates committed to a repository allow an attacker to impersonate your server or sign malicious code as if it were yours.
Internal infrastructure details. Hostnames, IP addresses, internal service URLs, VPN configurations — information that makes follow-on attacks significantly easier.
Proprietary source code. Beyond credentials, the code itself may contain business logic, algorithms, or product details that are commercially sensitive or reveal further vulnerabilities.
What attackers do within the first hour
Research on exposed credentials consistently shows the same pattern: automated tools find and abuse exposed credentials within minutes of a repository going public or a commit being pushed.
For AWS keys, the typical attack is immediate: spin up high-cost EC2 instances (often GPU instances for cryptocurrency mining) in every available region. AWS bills of tens of thousands of pounds can accumulate in hours. AWS does have some detection for this, but by the time an alert fires, the damage is often already significant.
For Stripe keys, attackers look for the ability to retrieve customer payment data, initiate refunds (to attacker-controlled accounts), or create unauthorised charges.
For email API keys (SendGrid, Mailgun, Postmark), the immediate use is high-volume spam or phishing campaigns — burning your sending reputation and potentially getting your domain blacklisted.
For GitHub tokens with write access, attackers can modify your codebase directly — introducing backdoors, exfiltrating your other secrets, or wiping repositories.
What to do immediately if your repository was accidentally public
1. Make the repository private immediately. This stops new exposure but does not undo existing exposure — if bots have already scraped the repo, the credentials are already compromised.
2. Assume every secret in the repository is compromised. Treat this as a known breach, not a maybe. Move to revocation immediately.
3. Revoke every credential that was in the repository. AWS Console → IAM → access keys. Stripe Dashboard → Developers → API keys. Go through every service. Invalidate, do not just rotate — a key you rotate is still valid for the minutes between rotation and the attacker using it.
4. Generate new credentials. Create fresh credentials for each service. Use the minimum permissions necessary. Store them properly (see below).
5. Check for abuse. Look at usage logs for each service. AWS CloudTrail for unusual API calls. Stripe for unexpected activity. Your email platform for unusual sending patterns. If you find evidence of abuse, treat it as a security incident and notify affected parties as appropriate.
6. Clean the repository history. Removing the secret from the current commit is not enough — it still exists in git history. Use git filter-repo (the recommended tool, replacing the older git filter-branch) to remove sensitive files from the entire history:
git filter-repo --path .env --invert-pathsAfter rewriting history, force-push to GitHub. GitHub also has a cached view of deleted content that can persist — contact GitHub support to request removal of cached sensitive data.
7. Enable GitHub secret scanning. GitHub scans public repositories for known secret patterns and notifies you. For private repositories, secret scanning is available on GitHub Advanced Security. Enable push protection to block commits containing secrets before they are pushed.
How to prevent this from happening
.gitignore before the first commit. The most important habit. Before running git init or making your first commit on any project, add a .gitignore file that excludes .env, *.pem, *.key, and any other files that should never be committed. GitHub provides language-specific .gitignore templates that cover the most common cases.
Environment variables, not hardcoded values. API keys and credentials should never appear as string literals in source code. Use environment variables locally (.env with dotenv) and proper secrets management in production (AWS Secrets Manager, HashiCorp Vault, Railway environment variables, Vercel environment variables).
Pre-commit hooks. Tools like git-secrets (AWS) or detect-secrets (Yelp) can be configured as pre-commit hooks that scan your staged changes for credential patterns and block the commit if they find any. One-time setup, persistent protection.
Regular repository audits. Use Olimpio's secrets scanner to check your connected repositories for exposed credentials automatically. It checks for patterns matching AWS keys, Stripe keys, Twilio, SendGrid, and dozens of other services — surfacing anything it finds with the file location, repository name, and a masked value. Connect your GitHub account and run a scan.
Principle of least privilege on all tokens. A GitHub personal access token that only needs to read from one repository should not have write access to all repositories. A Stripe key used for reading customer data should not have permission to initiate refunds. Limiting permissions limits the blast radius when — not if — a credential is eventually exposed.
The git history problem
One aspect of this that catches developers off guard: git history is permanent unless you actively rewrite it. If you committed a secret three months ago and then removed it in a subsequent commit, the secret is still present in your repository history. Anyone with access to the repository can run git log -p and find it.
This applies to private repositories too — a repository that was private when the secret was committed but later made public exposes all of its history, including the now-deleted credential.
The fix is git filter-repo. If you discover old secrets in your history, rewrite the history, force-push, and rotate the credentials. If the repository has collaborators or forks, they will need to rebase — which is disruptive, but necessary.
Olimpio's secrets scanner checks repository history for exposed credentials, not just the current state — so it will surface historical exposures as well as current ones.
Run a secrets scan on your repositories with Olimpio to check for exposed credentials across your current files and commit history.