A private key is the half of a key pair that proves who you are. If it is exposed, anyone can log in to every place that trusts its public half, with no password prompt and nothing to guess. There is no provider to ask for a new one and no “revoke” button: you have to remove the matching public key from every place that trusts it, then generate a new pair. That list of places is the real work, so start by finding it.
Check your GitHub account for leaked secrets — free
- Provider
- Other
- Severity
- Critical
- Impact
- Source code and build access
- Checked live by LeakWatch
- Yes
What a private key looks like
Private keys are text files that start and end with a marker line. The line tells you the format:
-----BEGIN OPENSSH PRIVATE KEY----- modern OpenSSH format (Ed25519, RSA, ECDSA)
-----BEGIN RSA PRIVATE KEY----- RSA, older PEM format
-----BEGIN EC PRIVATE KEY----- elliptic-curve, PEM format
-----BEGIN PRIVATE KEY----- PKCS#8, any algorithm
-----BEGIN ENCRYPTED PRIVATE KEY----- PKCS#8 protected by a passphrase
Between the markers is a block of base64 text; this page never shows one, and neither should you paste one anywhere. A .pub file, or a line starting with ssh-ed25519 or ssh-rsa, is the public key and is safe to share.
Do not assume a BEGIN PRIVATE KEY block is an SSH key. The same format holds TLS certificate keys, JWT signing keys and code-signing keys, and each one is revoked differently (see the FAQ). PGP keys have their own BEGIN PGP PRIVATE KEY BLOCK header and a separate LeakWatch rule.
How private keys get leaked
- A whole
~/.sshdirectory in a repository. Often via a dotfiles repo, or agit add .in the home folder. - Keys baked into Docker images and CI. A
COPY id_rsaor anARGin a Dockerfile (they remain in image layers), or a deploy key pasted into a workflow file instead of the secrets store. - Backups and archives. A zipped project folder, a backup of a laptop or server pushed to a public repository or bucket.
- Test fixtures and sample configs. A real key used to “make the example work” in a
tests/orexamples/folder. - Pasted for help. In an issue, a chat or a forum post, while asking why authentication fails.
What to do in the first hour
- Identify the key and what trusts it. Work out the public key that goes with it. If you still have the private file,
ssh-keygen -y -f <file>prints the public key andssh-keygen -l -f <file>prints its fingerprint. Then list where it might be installed: servers (~/.ssh/authorized_keysof each user, and/root/.ssh/authorized_keys), GitHub and GitLab (account SSH keys and repository deploy keys), cloud key pairs, CI/CD settings, Git hosting for other teams, and any bastion hosts. - Remove the public key from every one of those places. On servers, delete its line from
authorized_keys. On GitHub, open Settings → SSH and GPG keys, and repository Settings → Deploy keys. Do this before you generate a replacement, so there is no window where the leaked key still works. Deleting a key pair in a cloud console does not remove it from instances that already have it, so check the instances too. - Generate a new pair, protected by a passphrase.
ssh-keygen -t ed25519 -C "<purpose>"creates one, and the passphrase prompt protects the file if it leaks again. Use a separate key per purpose (one per server group, one for CI) so a single leak does not unlock everything. - Look for logins made with the old key. On Linux servers,
sshdlogs accepted public-key logins with the key fingerprint, in/var/log/auth.logor viajournalctl -u ssh(orsshd). Search for the fingerprint from step 1. Also look atlastfor unfamiliar sources. - Look for persistence on any machine it could reach. An attacker who got in often adds their own key to
authorized_keys, creates a user, adds a cron job or a systemd unit. If you find any of these, treat the machine as compromised and rebuild it rather than clean it. - Rotate what lived on those machines. Environment variables, config files and anything else readable by the login user.
- Then clean the repository: remove the file, add it to
.gitignore, and rewrite history if you want to. See I accidentally pushed an API key to GitHub.
Not sure what else leaked from the same repository? Run a free scan.
Revoke it at the places that trust the key
A key has no issuer, so you revoke it by removing trust. For SSH, that means deleting the public key from each authorized_keys file, from your Git hosting account and deploy keys, and from any CI or cloud setting that holds it; there is no central list to query. The fingerprint from step 1 is your search term. If the key was a server host key (in /etc/ssh/ssh_host_*_key) rather than a login key, regenerate the host keys on that server and let your users know their clients will warn about the change.
How LeakWatch detects it
LeakWatch matches a block that starts with a BEGIN … PRIVATE KEY marker and ends with the matching END marker. It does not check this type live, and it could not: a private key is proof of possession, not a token you can send to a server and ask “is this still active?”, and testing it would mean using someone else’s key to sign in. Instead LeakWatch analyzes the key itself, offline: whether it is a real key rather than a template or a truncated block, and whether it is protected by a passphrase. It can tell you the key is exposed, not whether it still opens anything. Assume it does until you have removed it everywhere.
LeakWatch can check whether a detected key is still active with a read-only request to Other. It never reads your data or spends your credits.
FAQ
My key has a passphrase. Is it still a leak?
Yes, but a less urgent one. The attacker has to guess the passphrase offline first, and a long random one makes that impractical. A weak passphrase will not hold for long. Rotate the key either way: you cannot know how strong the passphrase really is.
The block starts with BEGIN PRIVATE KEY. Is it still SSH?
Not necessarily. If it is a TLS certificate key, ask the certificate authority to revoke the certificate and issue a new one with a new key. If it signs tokens (JWT), rotate it and invalidate sessions it signed. If it is a code-signing key, contact the issuing authority. Check how you used it before deciding.
Can I just delete the key from the server and keep using the same pair elsewhere?
No. The point of rotating is that the exposed pair stops being trusted anywhere. Create a new pair and move every use to it.