← all checksmoney leak
Stripe test mode vs live mode: are you mixing keys?
Stripe gives you two completely separate worlds — test and live — that share almost identical keys and dashboards. Mixing them up is an environment-variable typo away, and it's expensive in both directions.
how it actually happens
How test and live keys get mixed up
It’s rarely a dramatic mistake. It’s usually one of these, each of them ordinary:
- A
.env.localwith test keys gets copied straight into the production environment variables when a project is deployed for the first time, and nobody swaps it before launch. - A staging environment is set up once with live keys “to test the real flow,” and the intention to switch it back to test mode never happens.
- A key is rotated in the Stripe dashboard — for a new restricted key, or after a scare — and only some of the places it’s used get updated.
- A webhook endpoint is registered against the live Stripe account but the app’s server is still verifying it against the test-mode signing secret, so every real webhook silently fails verification.
why it's dangerous both ways
Wrong in either direction costs you something real
| what happens | the cost | |
|---|---|---|
| Test key in production | Real customers try to pay and every charge silently fails, or succeeds against a test-mode account that never actually collects money. | Lost revenue, and a support queue full of confused customers. |
| Live key in a test or staging script | A script written to "just try the checkout flow" runs against real Stripe, and a real card gets a real charge. | A refund to issue, and a live key now sitting in a place with weaker access controls than production. |
check it yourself
A 5-minute self-check
- Every Stripe key you use starts with either
sk_test_/pk_test_orsk_live_/pk_live_— check your production environment variables and confirm every one is alivekey, and every one in a local/staging/preview environment is atestkey. - Do a real (small, refundable) checkout on your production URL and confirm it shows up in Stripe's live-mode dashboard, not test mode.
- Check that your webhook endpoint's signing secret in your server's environment variables matches the one shown for that specific endpoint in the Stripe dashboard — each endpoint has its own secret.
what Solacess adds
P5: checked across your environments automatically
P5Test and live keys mixed across environments — confirmed by checking which mode the keys your app is actually configured with belong to, not by trusting an environment variable's name.
test mode only, always
Every active Stripe check Solacess runs — P1 through P4 — refuses to run against anything but a Stripe test-mode key. If your app is pointed at a live key where Solacess expects test mode, the scan stops rather than risk a real charge.
See how a P5 finding is reported, with the environment it was found in.
The sample report is a real scan of a deliberately vulnerable app — nine findings, the proof behind each one, and what they would cost.