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
Store keys in environment variables
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.
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.
Add .env to .gitignore
Add .env to .gitignore
Ensure your .env file is never committed to Git. Add it to .gitignore before your first commit.
1# .gitignore2.env3.env.local4.env.production5.env.*.local6node_modules/Expected result: Git ignores .env files, preventing accidental commits of your secret keys.
Load environment variables in Node.js
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.
1// Install dotenv: npm install dotenv2require('dotenv').config();34const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);56// 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}1112console.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.
Create restricted API keys for limited access
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.
1// Using a restricted key that can only create charges2const stripeChargesOnly = require('stripe')(process.env.STRIPE_RESTRICTED_KEY);34// This works — charges permission is granted5async 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}1314// This would fail — customer permission not granted15// const customers = await stripeChargesOnly.customers.list(); // Error!Expected result: The restricted key can only perform authorized actions. Unauthorized operations throw a permissions error.
Rotate keys when compromised
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.
1// After rotating your key in the Dashboard:2// 1. Update the key in your environment variables / hosting platform3// 2. Restart your application to pick up the new key4// 3. Test that payments still work56// Verify the new key is active7async 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}1516verifyKey();Expected result: The new key works, and the old key is invalidated after the grace period.
Complete working example
1require('dotenv').config();23// Validate required environment variables at startup4const REQUIRED_VARS = [5 'STRIPE_SECRET_KEY',6 'STRIPE_PUBLISHABLE_KEY',7 'STRIPE_WEBHOOK_SECRET',8];910const 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}1617// Warn if using live keys in development18if (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}2324const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY, {25 apiVersion: '2024-12-18.acacia',26 maxNetworkRetries: 2,27});2829module.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.
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.
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation