Skip to content
web-securityintermediate#secrets-management#api-keys#appsec#incident-response#devsecops

Leaked API Keys: How Secrets Leak and What to Do

How API keys and tokens leak through git, logs, images and laptops, what attackers do with them, and the first-hour response that revokes them.

An API key is a password that software uses. A Stripe secret key moves money, an AWS access key creates servers, an npm token publishes packages under your name, an OpenAI key bills model calls to your card. None of them ask for a second factor, and most providers send no alert when a new IP address starts using one.

That makes leaked keys one of the cheapest ways into a company. Nobody has to phish anyone or exploit anything. Someone finds the string and uses it.

How big the problem is

GitGuardian scans public GitHub continuously. In 2024 it scanned 69.6 million public repositories and found at least one secret in 4.61% of them, and 15% of commit authors had leaked a secret. The figure that matters most for response is the next one: 70% of the secrets leaked in 2022 were still valid when GitGuardian published its 2025 report. Most leaked keys stay valid for years.

Public GitHub is only the visible part. The same report covers secrets in public Docker images, and private repositories, chat and ticketing tools carry far more that no outside scanner sees.

Where keys leak

ChannelHow it happensWho finds it
Git commitsA .env or config file is committed, or a key is pasted into code "just to test". Deleting it later leaves it in history.Public-repo scanners within minutes (Unit 42 saw AWS keys used five minutes after a push); anyone with repo access later
Container imagesCOPY . . in a Dockerfile copies .env and .git into a layer. Layers keep deleted files.Anyone who pulls the image from a public registry
Frontend and mobile codeA secret key is used from the browser or bundled into an app. Minification hides nothing.Anyone who opens dev tools or unpacks the app
CI logsA build step echoes environment variables or runs with debug output on.Anyone who can read the build logs, which may be public for open-source projects
Chat, tickets, AI assistantsSomeone pastes a config or log to get help.Every member of the channel, the vendor, and anyone who breaches it
Terraform stateState files store resource attributes in plain text, including generated passwords and keys.Anyone who can read the state bucket
Developer laptopsInfostealer malware takes .env files, shell history, browser-saved tokens and cloud CLI credentials.The stealer operator, then buyers of the logs

The last row is easy to forget. A stealer on one developer's laptop can take the AWS CLI credentials, a GitHub token and every .env in their projects in one sweep. Our guide on what an infostealer takes covers that path.

What attackers do with a key

What happens next depends on what the key can do.

  • Cloud keys (AWS, Google Cloud, Azure, DigitalOcean) are used to launch crypto-mining instances, read storage buckets, and create new access keys or users so access survives a rotation.
  • Payment keys (Stripe, Square) are used to test stolen card numbers, read customer and payment data, or refund charges the attacker made with stolen cards.
  • Source and package tokens (GitHub, GitLab, npm, PyPI) are used to read private code for more secrets, or to publish a malicious package version. That turns one leak into a supply-chain attack on everyone who installs the package.
  • Email and messaging keys (SendGrid, Mailgun, Twilio, Slack) are used to send phishing from your verified domain, which passes SPF and DKIM, or to read internal channels.
  • AI keys (OpenAI, Anthropic and others) are resold or used to run large workloads billed to you.

The 2016 Uber breach is the standard example. According to the FTC's complaint, attackers used an AWS access key that an Uber engineer had left in plain text in code in a private GitHub repository. They reached the repository because engineers' GitHub accounts reused passwords and had no multi-factor authentication, then downloaded files from Uber's S3 storage holding about 25.6 million names and email addresses of US riders and drivers. Uber later put the worldwide total at 57 million people.

The first hour after a leak

Work in this order. The most common mistake is to start with the git history.

  1. Revoke or rotate the key at the provider. This is the only step that stops an attacker who already copied it. Create the replacement, deploy it, then delete the old one. If you cannot deploy quickly, revoke first and accept the outage.
  2. Check the provider's logs for use since the leak. Look for calls from IP addresses, regions or user agents you do not recognise, and for new credentials the attacker may have created.
  3. Look for persistence. On AWS, list access keys, users, roles and Lambda functions created since the leak. On GitHub, check new deploy keys, OAuth apps and webhooks. Attackers create a second way in before you rotate the first.
  4. Find every copy. Forks, clones, Docker image tags, CI caches, wiki pages, chat messages and backups. Rotate any other secret that sat in the same file.
  5. Clean up the source. After revocation, remove the secret from history with git filter-repo or BFG Repo-Cleaner, rebuild affected images, and purge logs where you can.
  6. Write down the cause and add the control that would have stopped it. Usually that is a scanner in the commit path or a move to short-lived credentials.
Illustrated cybersecurity scene for Leaked API Keys: How Secrets Leak and What to Do
Illustration for Leaked API Keys: How Secrets Leak and What to Do.
ProviderRevoke or rotateCheck usage in
AWSIAM, the user, Security credentials: deactivate, then delete the keyCloudTrail, filtered on the access key id
Google CloudService account Keys tab, or API key credentials pageCloud Audit Logs
GitHubDeveloper settings, Personal access tokensAccount security log and organization audit log
StripeAPI keys page: rotate the key and expire the old one now (a dashboard rotation otherwise keeps it working for up to 7 days)Workbench request logs, or the key's own request logs
SlackApp settings, OAuth: revoke tokensIntegration logs under Manage apps; Audit Logs on Enterprise Grid
OpenAI or AnthropicAPI keys page in the consoleUsage dashboard
AWS quarantine is a stopgap

When AWS detects one of your access keys exposed publicly, it can attach the AWSCompromisedKeyQuarantineV3 managed policy to the IAM user, which denies a list of high-risk actions, and opens a support case. The key still works for anything the policy does not deny. The policy also denies creating, deleting and updating access keys for that user, so rotate from a different admin identity, and investigate as if no quarantine had happened.

How to find leaked secrets you already have

Scan before an attacker does.

  • Repositories: run gitleaks or TruffleHog against the full history, including all branches. Both detect hundreds of key formats. TruffleHog also checks by default whether a found key is still live, which sends it to the provider, so pass --no-verification when scanning anything other than your own keys.
  • Logs, configs and snippets: before you paste a log into a ticket, chat or AI assistant, run it through our secret scanner. It finds keys from 40 providers, private keys, tokens and database URLs in your browser, and gives you a redacted copy to share.
  • Images: scan container images in your registry, not only the Dockerfile, since deleted files survive in earlier layers.
  • Cloud config: check that Terraform does not write secrets as literal strings. Our cloud baseline checker flags them along with other risky settings.

How to defend

  1. Block secrets at commit and push. Add gitleaks or TruffleHog as a pre-commit hook and in CI. On GitHub, push protection for users is on by default and blocks pushes containing supported secrets to public repositories; enable it for private repositories too where your plan allows.
  2. Keep secrets in a secret manager. AWS Secrets Manager, Google Secret Manager, HashiCorp Vault or your platform's encrypted environment variables. Commit an .env.example with placeholders and add .env to .gitignore.
  3. Replace static cloud keys with short-lived credentials. CI systems such as GitHub Actions and GitLab can exchange an OIDC token for short-lived cloud credentials, one hour by default on AWS and Google Cloud. Workloads should use instance roles, workload identity or IRSA rather than key files.
  4. Scope every key. Restricted Stripe keys, fine-grained GitHub tokens, Google API keys limited by API and referrer, IAM policies with only the actions needed. A leaked scoped key does less damage.
  5. Never put secret keys in client code. Anything shipped to a browser or a phone is public. Proxy the call through your backend.
  6. Rotate on a schedule so rotation is routine and fast when it is urgent. A team that has never rotated a key will take days the first time.
  7. Protect the laptops. Endpoint protection, no long-lived credentials in shell profiles, and a plan to rotate everything on a machine that catches a stealer. Our session kill switch lists where to revoke sessions and tokens across the major platforms.

Sources & further reading