PAY-5Required
Keep test and live modes apart
Use the provider's test mode in every environment except production, and make the app refuse to start with a live key anywhere else.
How to do it
Providers give separate test and live API keys and separate webhook secrets. Keep them per environment in a secrets store. Check the key prefix at startup, such as sk_live_ and sk_test_ at Stripe. Use restricted keys with only the permissions the app needs. Never copy live customer or payment data into test. Test systems also must not email, text or push to customers, as Never contact customers from test systems says.
Examples
JavaScript example
const isLiveKey = key => /^(sk|rk)_live_/.test(key)
if (isLiveKey(process.env.PAYMENT_API_KEY) !== (process.env.APP_ENV === 'production')) {
throw new Error('Payment key mode does not match APP_ENV')
}
Python example
import os, re
def is_live_key(key: str) -> bool:
return re.match(r"^(sk|rk)_live_", key) is not None
if is_live_key(os.environ["PAYMENT_API_KEY"]) != (os.environ["APP_ENV"] == "production"):
raise SystemExit("Payment key mode does not match APP_ENV")
How to check
Start staging with a live key. It exits with an error. Search the repository for sk_live_ and rk_live_. Nothing is found.
Sources
Related rules
- TST-58 Make the test setup refuse production in Testing
- API-80 Give each environment its own provider key in API design
- ENG-26 Keep secrets in a secrets store in Engineering
- NTF-8 Never contact customers from test systems in Notifications
- INF-10 Give each environment its own account in Infrastructure and environments
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/payments/card-security-and-sca/test-and-live-keys">Agent Wranglers payments and billing playbook</a>. In code you write, add a comment next to it with the same link.