Skip to main content
RapidDev - Software Development Agency
stripe-guide

How to securely store Stripe secret keys

Stripe secret keys (sk_live_ and sk_test_) grant full access to your Stripe account and must never appear in source code, frontend files, or version control. Store them in environment variables, use .gitignore to exclude .env files, rotate keys periodically, and use restricted keys for services that only need specific permissions. This guide covers all best practices with practical examples.

What you'll learn

  • How to store Stripe keys in environment variables safely
  • How to configure .gitignore to prevent accidental key commits
  • How to use restricted API keys for limited-access services
  • How to rotate keys without downtime
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner5 min read10 minutesAll platforms, Node.js 18+March 2026RapidDev Engineering Team
TL;DR

Stripe secret keys (sk_live_ and sk_test_) grant full access to your Stripe account and must never appear in source code, frontend files, or version control. Store them in environment variables, use .gitignore to exclude .env files, rotate keys periodically, and use restricted keys for services that only need specific permissions. This guide covers all best practices with practical examples.

Protecting Your Stripe API Keys

Your Stripe secret key grants complete access to your account — charges, refunds, customer data, everything. A leaked key can result in fraudulent charges, data theft, and account compromise. The solution is simple: never hardcode keys in source code. Use environment variables, restrict access with scoped keys, and rotate keys if you suspect exposure.

Prerequisites

  • A Stripe account with API keys (Dashboard → Developers → API keys)
  • Node.js 18 or later installed
  • Basic understanding of environment variables

Step-by-step guide

1

Store keys in environment variables

Create a .env file in your project root to hold your Stripe keys. Your application reads them at runtime without exposing them in source code.

typescript
1# .env file (DO NOT commit this file)
2STRIPE_SECRET_KEY=sk_test_51ABC123...
3STRIPE_PUBLISHABLE_KEY=pk_test_51ABC123...
4STRIPE_WEBHOOK_SECRET=whsec_ABC123...

Expected result: Your keys are stored in a file that is excluded from version control.

2

Add .env to .gitignore

Ensure your .env file is never committed to Git. Add it to .gitignore before your first commit.

typescript
1# .gitignore
2.env
3.env.local
4.env.production
5.env.*.local
6node_modules/

Expected result: Git ignores .env files, preventing accidental commits of your secret keys.

3

Load environment variables in Node.js

Use the dotenv package to load your .env file in development. In production, set environment variables directly on your hosting platform.

typescript
1// Install dotenv: npm install dotenv
2require('dotenv').config();
3
4const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
5
6// Verify key is loaded (never log the actual key)
7if (!process.env.STRIPE_SECRET_KEY) {
8 console.error('ERROR: STRIPE_SECRET_KEY not set');
9 process.exit(1);
10}
11
12console.log('Stripe initialized with key ending in:',
13 process.env.STRIPE_SECRET_KEY.slice(-6));

Expected result: The Stripe SDK initializes with the key from the environment variable. The full key is never logged.

4

Create restricted API keys for limited access

If a service only needs to create charges, create a restricted key with only that permission. Go to Dashboard → Developers → API keys → Create restricted key.

typescript
1// Using a restricted key that can only create charges
2const stripeChargesOnly = require('stripe')(process.env.STRIPE_RESTRICTED_KEY);
3
4// This works — charges permission is granted
5async function createCharge() {
6 const pi = await stripeChargesOnly.paymentIntents.create({
7 amount: 5000,
8 currency: 'usd',
9 payment_method_types: ['card'],
10 });
11 return pi;
12}
13
14// This would fail — customer permission not granted
15// const customers = await stripeChargesOnly.customers.list(); // Error!

Expected result: The restricted key can only perform authorized actions. Unauthorized operations throw a permissions error.

5

Rotate keys when compromised

If you suspect a key has been exposed, roll (rotate) it immediately in the Stripe Dashboard. Stripe lets you roll keys without downtime by keeping the old key active for a grace period.

typescript
1// After rotating your key in the Dashboard:
2// 1. Update the key in your environment variables / hosting platform
3// 2. Restart your application to pick up the new key
4// 3. Test that payments still work
5
6// Verify the new key is active
7async function verifyKey() {
8 try {
9 const balance = await stripe.balance.retrieve();
10 console.log('Key is valid. Balance available:', balance.available);
11 } catch (err) {
12 console.error('Key verification failed:', err.message);
13 }
14}
15
16verifyKey();

Expected result: The new key works, and the old key is invalidated after the grace period.

Complete working example

secure-stripe-config.js
1require('dotenv').config();
2
3// Validate required environment variables at startup
4const REQUIRED_VARS = [
5 'STRIPE_SECRET_KEY',
6 'STRIPE_PUBLISHABLE_KEY',
7 'STRIPE_WEBHOOK_SECRET',
8];
9
10const missing = REQUIRED_VARS.filter(v => !process.env[v]);
11if (missing.length > 0) {
12 console.error('Missing required environment variables:', missing.join(', '));
13 console.error('Create a .env file or set them in your hosting platform.');
14 process.exit(1);
15}
16
17// Warn if using live keys in development
18if (process.env.NODE_ENV !== 'production' &&
19 process.env.STRIPE_SECRET_KEY.startsWith('sk_live_')) {
20 console.warn('WARNING: Using live Stripe keys in development!');
21 console.warn('Switch to test keys (sk_test_) for development.');
22}
23
24const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY, {
25 apiVersion: '2024-12-18.acacia',
26 maxNetworkRetries: 2,
27});
28
29module.exports = {
30 stripe,
31 PUBLISHABLE_KEY: process.env.STRIPE_PUBLISHABLE_KEY,
32 WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
33};

Common mistakes when securelying store Stripe secret keys

Why it's a problem: Hardcoding sk_live_ keys directly in source code

How to avoid: Always use environment variables. If keys are in code, rotate them immediately and move to env vars.

Why it's a problem: Committing .env files to Git

How to avoid: Add .env to .gitignore before the first commit. If already committed, remove from history with git filter-branch or BFG Repo-Cleaner, then rotate keys.

Why it's a problem: Using the same key for all services and environments

How to avoid: Use test keys (sk_test_) in development and restricted keys for services that do not need full access.

Why it's a problem: Logging the full API key in error messages or server logs

How to avoid: Only log the last 4-6 characters for identification. Never log the full key.

Best practices

  • Store all Stripe keys in environment variables, never in source code
  • Add .env to .gitignore before your first commit
  • Use restricted API keys for services that only need specific permissions
  • Use test keys (sk_test_) in development and staging environments
  • Rotate keys immediately if you suspect exposure
  • Validate that required environment variables are set at application startup
  • Warn loudly if live keys are detected in a development environment
  • Use a secrets manager (AWS Secrets Manager, Google Secret Manager, Vault) in production

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

How do I securely store my Stripe API secret key? I want to make sure it never ends up in my Git repository or frontend code. Show me Node.js best practices with environment variables.

Stripe Prompt

Help me set up a secure Stripe configuration for my Node.js app. I need environment variable loading with validation, .gitignore setup, and restricted key usage for a service that only creates charges.

Frequently asked questions

What happens if my Stripe secret key is leaked?

Anyone with your secret key can create charges, issue refunds, access customer data, and more. Rotate the key immediately in Dashboard → Developers → API keys → Roll key.

Can I use the same key for test and live mode?

No. Test keys (sk_test_) and live keys (sk_live_) are separate. Use test keys in development and live keys only in production.

Is it safe to commit my publishable key (pk_test_)?

Publishable keys are designed to be used in client-side code and are not secret. However, it is cleaner to use environment variables for all keys to maintain consistency.

How do restricted keys differ from regular secret keys?

Restricted keys have limited permissions that you define (e.g., only create charges, only read customers). Regular secret keys have full access to everything in your Stripe account.

Should I use a secrets manager instead of .env files?

In production, yes. AWS Secrets Manager, Google Secret Manager, or HashiCorp Vault provide encryption, access control, and audit logging. For local development, .env files with dotenv are sufficient.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.