The direct answer: treat a secret key committed to GitHub as potentially copied. Revoke or rotate it at the provider first, put a replacement in protected server-side settings, and test the app. Then check activity and charges during the exposure window, remove the value from current code, and decide whether repository-history cleanup is worth the disruption. Deleting a line or making a repository private does not disable a credential already copied.
First confirm what was exposed
An API key is a credential that lets software use a service. Some values are intentionally public, such as certain browser-side publishable keys. Others can spend money, access private data or administer an account. Look at the provider's own description and the key's permissions. Do not paste the value into a chatbot, issue, screenshot, support ticket or public “key checker” while investigating.
Write down the provider, the key's label or identifier, which repository and branch contained it, whether that repository was public, and approximately when it was first committed. A private repository is not a guarantee of safety: collaborators, integrations, logs and past copies can still have access. If you cannot establish that a value was deliberately publishable, handle it as a secret until you can confirm otherwise.
Contain the incident before tidying Git
- Go to the provider's security or API-key page. Find the affected credential by its non-secret identifier. Revoke it, disable it or rotate it using the provider's supported process. For a key that can read customer data, make payments or incur large charges, treat this as urgent. If you lack access, ask the account owner or provider support immediately.
- Replace it safely. Create a new key with only the permissions the app needs. Set it in your host's protected server-side environment or secrets manager. Update every service that legitimately used the old key, then deploy or restart as required. Do not put the replacement in a frontend variable, GitHub source file or pasted deployment command.
- Prove the old one is unusable. Confirm the provider marks it revoked or disabled. Test the affected app function using the new key in a controlled way. If a shared key served several apps, inventory all of them so one quiet background job does not remain broken.
Some systems need a staged rotation to avoid an outage. Follow the provider's procedure for that specific credential, but limit the old key's lifetime and privileges as much as possible. A restart alone does not revoke a stolen key. If the provider cannot revoke an individual credential, ask what account-level action is needed.
Find out what the key could have done
The question is not merely “was the repository public?” It is “what could someone do with this key during the period it worked?” Check its scope: read-only or write access, production or test environment, account-wide or project-specific, and any spending limit. Record when the key was created, first exposed and finally disabled. That is your provisional exposure window.
Look at the provider's usage and audit records for unexpected requests, unfamiliar IPs or regions, unusual data reads, new resources, payments or charges. Compare them with normal app traffic. Review your own app and billing logs where appropriate, without copying more secrets into the investigation notes. Providers differ in what they log, and logs may expire. No alert does not prove nobody used the key.
If the key could access customer information, change production data or spend money, involve someone qualified to assess the impact. Contact the provider about suspicious use or charges. If personal data may have been accessed, get suitable legal and incident-response advice about any reporting or customer notification duties. Do not claim “no breach” just because you have not found a clear trace.
Clean the repository without confusing cleanup with containment
Remove the literal value from the current files and replace it with a setting name and a harmless example value. Add local secret files to .gitignore, but understand that this only prevents future accidental additions; it does not erase earlier commits. Search relevant branches, tags, pull requests, CI logs and generated build artifacts for the old value using tools that keep the value private. Ask collaborators not to repeat it in chat while coordinating.
Git history is designed to retain old versions. GitHub's guidance says revoking or rotating a secret is the first step and may be sufficient; rewriting history has side effects, including changed commit identifiers and the risk of an old clone reintroducing the data. If the exposed material includes something you cannot revoke, or policy requires removal, plan history cleanup with collaborators and GitHub's documented procedure. Do not force-push a rewrite on a shared repository without coordination. Even a successful rewrite cannot promise that every external copy disappears.
If GitHub sent a secret-scanning alert, resolve it accurately after the key is invalidated. Do not mark an active credential as harmless merely to clear a warning. Secret scanning can help find known patterns but does not prove every credential has been detected.
Close the gap that allowed the commit
Make a small private incident record: what was exposed, when it was disabled, what was checked, any suspected misuse, who owns remaining actions, and when the app was confirmed working again. Avoid storing the actual key in that record. Then add guardrails: a local secret file excluded from Git, an example configuration file with placeholders, least-privilege keys, separate test and live credentials, and provider usage alerts or spending limits where available.
Ask your AI coding assistant to point to the exact server code that reads each secret and to check whether the deployed browser bundle or public files contain it. Have a human review any suggested Git-history rewrite or production credential rotation. The earlier guide to where API keys belong explains the safe architecture; this checklist is for the moment a key has already escaped.
The sequence above follows GitHub's guidance on removing sensitive repository data and the OWASP secrets-management guidance. Both distinguish revocation and incident response from merely editing source files.
Where Ship Doctor helps
KHDS Ship Doctor helps vibe coders and non-technical founders inspect the actual app and collect evidence about production risks. The free builder creates a starter instruction; the £49 one-off toolkit adds reusable workflows, evidence templates and a remediation plan. Its public sample report shows how confirmed findings and unverified areas are separated. For broader checks, see the vibe coding security checklist and AI-built app launch checklist.
Frequently asked questions
Is deleting the GitHub file enough to protect an exposed API key?
No. A copy may remain in commits, clones, forks or logs. Disable the credential at its provider first, then clean the code and assess the history.
What should I do first if a secret key was pushed to a public repository?
Identify the provider without reposting the value, then revoke or rotate it promptly. Install the replacement in protected server-side settings and test the app.
Should I rewrite Git history after rotating the key?
It depends on what leaked and the remaining risk. Rewrites can disrupt collaborators and cannot guarantee every copy disappears. Coordinate one carefully if needed; do not delay revocation.
How can I tell whether someone used the exposed key?
Review the provider's activity, billing and audit records for the exposure window. Missing alerts are not proof of no use. Escalate possible data access or financial loss.
Check the project you actually built
Find the next exposed secret before it becomes an incident.
Create a free starter instruction or use the complete reusable Ship Doctor toolkit.