pk_test in production: why your checkout silently fails
A Stripe test key on your live site is not a security leak — it is a launch bug. Real cards will not be charged. Here is how to spot and fix it.
Stripe (and Clerk) give you two sets of keys: test (pk_test_ / sk_test_) and live (pk_live_ / sk_live_). If your production site is loading a pk_test_ key, you’re pointed at the test environment — and that’s a quiet, expensive mistake.
Why it’s easy to miss
Nothing errors. Checkout looks like it works, test cards "succeed," but no real money moves. You can launch, get traffic, and not realize for days that you haven’t taken a single real payment.
This is a bug, not a leak
Publishable keys (pk_) are public by design — having one in your frontend isn’t a security problem. The problem is the mode: test keys in a place that’s supposed to take real payments.
The fix
- Swap
pk_test_→pk_live_in your production build/env, and the matching secret key (sk_test_→sk_live_) server-side. - Keep test keys in your dev environment only.
- Verify a real end-to-end purchase after switching.
Shipshape flags a pk_test_ key on a live page so you catch this before your launch — not after. → Scan your app
FAQ
Is a pk_test key in my frontend a security risk?
No — publishable keys are public by design. The issue is functional: a test-mode key means real payments will not go through on your live site.
Why does my Stripe checkout work but I get no money?
You are probably running test keys (pk_test_/sk_test_) in production. Test cards succeed but no real charge happens. Switch to live keys and verify a real purchase.
Related questions
- How to choose a security scanner for a vibe-coded app
- How do scanners safely test your database rules?
- Shipshape vs Vibe App Scanner: scanner results vs launch proof
- Stripe webhook returned 200, but paid access still failed