# Protecting against compromised API keys

API keys are credentials that authenticate your integration to Stripe.
You're responsible for safely managing several types of [API Keys](https://docs.stripe.com/keys), including **secret keys** that should never be exposed outside your running integration.
If an unauthorized party obtains your secret key, they could impersonate your integration to conduct fraudulent activity which could result in financial losses to you, unauthorized payouts, or unwanted changes to your account configuration. To understand how to protect your Stripe API keys, follow our [best practices for managing secret API keys](https://docs.stripe.com/keys-best-practices).
To keep your business secure, you should take immediate action when you suspect an API key may be compromised.
Stripe is aware that bad actors who obtain Stripe users' API keys may try to trick users into enabling certain products under the threat of deactivation. **Stripe does not deactivate users for not adopting Stripe products.** See the [FAQ](#FAQ) below.
## Immediate actions
If you believe your integration's secret API key is compromised, you should **rotate the key** as soon as possible.
1. **Find the compromised key** in the Dashboard → Developers → [API keys](https://dashboard.stripe.com/apikeys).
1. Select "..." → **Rotate key**. This will create a new key and set the compromised key to expire.
1. Choose an expiration long enough to test your integration with the new key.
1. **Update your integration's backend** to use the new key.
1. **Confirm that your integration works** with the new key. You can select "..." → **View request logs** on the new key to confirm that your integration is using it.
1. **Delete the compromised key** by selecting "..." → **Delete key**. Deletion is effective immediately. You will still be able to view request logs for the deleted key.
## Remediation after key rotation
1. If you see new connected accounts you don’t recognize, unauthorized payouts, or external bank accounts you don't recognize, [pause payouts to them](https://docs.stripe.com/connect/pausing-payments-or-payouts-on-connected-accounts) or reject them immediately in the Dashboard.
1. [Reverse any payouts](https://docs.stripe.com/connect/payout-reversals) already sent to fraudulent bank accounts, and remove those bank accounts from your account. Payout reversals are not guaranteed to succeed, but you should initiate them as soon as possible to maximize the chance of recovery. If you need help reversing payouts, contact Stripe support.
1. [Refund any fraudulent charges](https://docs.stripe.com/refunds) as soon as possible to reduce the risk of disputes. If your Stripe balance is insufficient to cover the refunds, you will need to [add funds to your](https://docs.stripe.com/get-started/account/add-funds) [account](https://docs.stripe.com/get-started/account/add-funds) to unblock them.
1. In [Workbench](https://dashboard.stripe.com/workbench/logs), review recent usage of the key for unusual activity, such as activity patterns that don't correspond to what your integration does.
1. Rotate all additional secret and restricted keys in case more than one key was exposed.
1. If you discovered a new exposure during remediation — for example, a key committed to a repository or embedded in source code — rotate your keys again after fixing the vulnerability. Your replacement key may have been exposed in the same way as the key you replaced. Repeat the steps above until you are confident no live key has been exposed.
## Security best practices
Follow [best practices for managing secret API keys](https://docs.stripe.com/keys-best-practices). In addition to storing and handling keys safely, use a defense-in-depth approach to mitigate where and how a key can be used even if it falls into the hands of a bad actor. For example:
* **[Restrict your API key to specific IP addresses](https://docs.stripe.com/keys#limit-api-secret-keys-ip-address)**. Even if an IP address-restricted key is compromised, it cannot be used outside your environment.
* **[Use Restricted API Keys (RAKs) instead of secret keys](https://docs.stripe.com/keys-best-practices#limit-access)**. Configure multiple keys, each with only the specific permissions it needs to function, which limits the potential damage of a compromise. For example, your integration can use distinct API keys for receiving payments and creating payouts. Restricted keys are the best option if you need to share Stripe API keys with third-party applications.
General security hygiene can further reduce the risk of bad actors getting your keys or using them to harm your business. Practices you can adopt right away include:
* **Audit API key usage regularly**. Every Stripe API key has request logs that you can review for unexpected activity. From the API keys list, click the [View request logs](https://docs.stripe.com/keys#view-request-logs) option in the key's menu. Look out for anything you don't recognize, including unexpected charges, refunds, or connected accounts. If your key isn't using IP address restrictions, look for events from IP addresses you don't recognize.
* **Protect your Dashboard** with passkeys or single sign on (SSO), and audit your account configuration regularly.
* Use AI code-review tools with instructions to find security vulnerabilities in your code.
* **Keep your plugins and frameworks up to date** to mitigate supply-chain risks from your dependencies.
* **Disable debugging-related functions** in production systems. Never show environment information (such as the values of environment variables) in error messages.
## Why was my key compromised?
Stripe's security team monitors the internet for exposed Stripe API keys. A small number of problems account for most of the compromises.
### Frontend environment variable misuse
Modern frontend frameworks automatically bundle certain environment variables into files that are sent to browsers. These special variables are meant for safe, public values (analytics IDs, publishable keys), **not secret keys**. If you put a secret key in such a variable, the secret will be inlined into your JavaScript bundle or initial HTML and will be visible to anyone who visits your site.
Never put a secret API key (prefixed `sk_live_` or `rk_live_`) in a variable that your framework bundles. Instead, store secret keys in a server configuration that is never shown to visitors. Examples of what to avoid in popular frameworks:
* **React, Create React App**: `REACT_APP_STRIPE_SECRET_KEY` — becomes visible to visitors.
* **Vue**: `VUE_APP_STRIPE_SECRET_KEY`
* **Vite**: `VITE_STRIPE_SECRET_KEY`
* **Nuxt**: `NUXT_ENV_STRIPE_SECRET_KEY`
* **Next.js, Vercel SSR**: _Any_ reference to a secret in page code may appear in initial server-rendered HTML.
* **Angular**: Secrets in `environment.ts` are bundled into JavaScript for browsers.
Consult your framework's documentation about safely using secrets, and consider using an automated scanner to flag misuse of secrets before they reach your users.
### Public code repositories
If you accidentally commit `.env` files or configuration files containing `sk_live_…` keys to a public repository on GitHub, GitLab, or similar, your keys are likely to be picked up by malicious web scrapers and reshared in hacker forums.
### CMS or plugin vulnerabilities (WordPress, Joomla, etc.)
Outdated or insecure Wordpress plugins (such as Elementor or Contact Form 7) can allow attackers to read configuration files like `.env` or `wp-config.php`, or to access your SQL database directly.
### Laravel misconfigurations
Laravel projects frequently rely on `.env` files for sensitive configuration, including `STRIPE_SECRET_KEY`. Common pitfalls include:
* `.env` files left in the web root and accessible directly (`https://example.com/.env`)
* **Debug mode enabled** (`APP_DEBUG=true`): error pages can dump environment variables, including Stripe keys.
* **Ignition debug panel left enabled in production**: exposes detailed stack traces and environment data, including Stripe keys.
### Mobile apps (Android APKs, Apple iOS)
When you hardcode an `sk_live_…` key directly into an app, it can be read by anyone who downloads the app.
## FAQ
### How did Stripe find the key?
Stripe's security team watches for exposed customer data — including API keys — across repositories, package registries, websites, and forums. If we find a secret key, we alert its owner and may invalidate it automatically.
### What’s the risk of a compromised key?
With your key, a bad actor can do anything that the key is configured to do, including:
* Create fraudulent charges or subscriptions
* Issue refunds, including to themselves
* Access customer data
* **For Connect platforms:**
  * Change payout destinations
  * Create payouts
  * Create connected accounts, transfer funds between platforms and their connected accounts
### What happens if Stripe invalidates my key automatically?
Stripe determined with high confidence that your key was compromised, invalidated it to prevent abuse, and began the process of key rotation described above. You must complete that process:
1. Create a new key in the Dashboard.
1. Update your integration to use the new key.
1. Test to confirm functionality.
### How can I protect my Connect platform against key takeovers?
When a key is compromised on a Connect platform, the key can be used to create new connected accounts, update payout accounts, or move and pay out funds. Ensure that you have secured your API keys with the best practices listed above.
Consider using [Radar for Platforms](https://docs.stripe.com/radar/radar-for-platforms) to monitor new accounts and pause payouts for elevated fraud scores.
Monitor your platform by listening on [Connect webhooks](https://docs.stripe.com/connect/webhooks) to get notified of `account.updated` events for new accounts, `account.external_account.updated` events to learn of changes to payout destinations, or `payout.created` for new payouts.
### I got an email saying that I had to enable a Stripe product or my Stripe account would be deactivated.
**The notice was not from Stripe.** Stripe does not threaten deactivation if users do not adopt Stripe products. How you integrate with Stripe is up to you.
A bad actor who has your Stripe key can't use it to log into your Stripe dashboard, but they may want to use your key to attack Stripe features you have not enabled. An email to you threatening deactivation may be an indirect attempt to gain access to those features.
Stripe always uses specific, easily identifiable domain names in communications. See Verified Stripe domains to learn how to assess whether an email is actually from Stripe.
