
This article is part of our AI-Built Site Rescue hub. Want help applying it? Talk to eSEOspace.
Before an AI-built app takes real money, verify your keys, webhook signatures, fulfillment, duplicate handling and live-mode setup. Each one can be checked in your own project.
The worry behind this list is simple: could someone get a product without paying? Who wrote the code matters less than whether anyone reviewed it.
This checklist is part of our AI-Built Site Rescue hub, and was checked against Stripe's documentation on 9 November 2026.
This article is general information, not legal or financial advice. A qualified reviewer should confirm your PCI duties.
Key Takeaways
- Stripe says only publishable keys are safe to expose outside your back end.
- Without webhook verification, Stripe says an attacker could send fake events to trigger order fulfillment or account access.
- Stripe says you can't rely on triggering fulfillment only from your checkout landing page.
- Stripe doesn't guarantee event order, and the same event can arrive more than once.
- Stripe's testing page prohibits testing in live mode with real payment details.
- Only test apps you own or have written permission to test. eSEOspace does not do penetration testing.
1. Check which keys are exposed
Stripe's API keys guide is direct: "Only publishable keys are safe to expose outside your application's back end."
Keys come in types you can recognize by their prefix.
| Key | Prefix | Safe to expose? |
|---|---|---|
| Publishable | pk_ | Yes |
| Restricted | rk_ | No |
| Secret | sk_ | No |
Stripe says a publishable key can identify your account, but it can't create charges or read account data.
The check. Search your own project for sk_live and rk_live. Look in the code, config files and repository history.
The common trap. Frontend tools publish some settings to the browser on purpose. Vite's environment variable guide says "VITE_* variables should not contain sensitive information such as API keys."
Next.js works the same way. Its environment docs say values prefixed NEXT_PUBLIC_ are inlined into JavaScript sent to the browser. Never give a secret key either prefix.
If a secret key has already been exposed, follow what to do in the first hour.
2. Reduce what a key can do
Stripe recommends restricted keys. Its key guide says it doesn't recommend secret keys for new use cases, because you can't limit their permissions.
A restricted key only has the permissions you assign. If it leaks, the damage is smaller. That reduces risk, but a leaked key is still an emergency.
3. Verify every webhook signature
A webhook is a message Stripe sends your server when something happens, such as a completed payment.
Stripe's webhook guide explains why signatures matter. "Without verification, an attacker could send fake webhook events to your endpoint to trigger actions like fulfilling orders, granting account access, or modifying records."
The check. Open your webhook handler. Confirm that it verifies the Stripe-Signature header with your signing secret, before it does anything else.
Stripe recommends its official libraries for this. It also says a framework can break verification: "Stripe requires the raw body of the request to perform signature verification."
If verification keeps failing, a parsing step may be altering the body. Do not fix that by removing the check.
Each endpoint has its own signing secret, and the secret differs between test and live. A secret copied from test will fail in live.
4. Fulfill from the webhook, not the thank-you page
Generated apps sometimes grant access when a shopper lands on a success page. Stripe's fulfillment guide warns against relying on that alone.
It says "You can't rely on triggering fulfillment only from your checkout landing page, because it's not guaranteed customers visit that page."
That failure works in the other direction too. A success page URL can be visited without a payment. So your server must confirm payment with Stripe before granting anything.
Stripe's guide says to check the Checkout Session's payment_status to determine whether it requires fulfillment.
5. Make fulfillment safe to run twice
Stripe's fulfillment guide warns that your fulfillment function might be called multiple times, possibly at the same moment, for one Checkout Session.
The webhook guide adds "Webhook endpoints might occasionally receive the same event more than once." Stripe suggests logging the event IDs you've processed, and skipping any you've already logged.
The check. Replay one test event twice in your sandbox. You should end up with one order and one email.
Order is not guaranteed either. Stripe's guide is blunt. "Stripe doesn't guarantee the delivery of events in the order that they're generated." Your handler should not assume one event arrives before another.
6. Reply fast, and handle retries
Stripe's guide says your endpoint should quickly return a 2xx status before any complex logic that might cause a timeout. Do the slow work after you reply.
Failed events come back. Stripe says it retries for up to three days in live mode, with an exponential back-off. In a sandbox it retries three times over a few hours.
So a bug that throws errors can create a backlog that lands all at once when fixed. That's another reason to make handling repeatable.
7. Keep price decisions on the server
If the browser sends the price to your server, a user can edit it. Set amounts on the server from your own product records. Then compare what you charged with what the order should cost.
Treat anything from the browser as untrusted, including quantities, discount codes and plan names. Our broken access control guide covers the same idea for data.
8. Test properly in a sandbox
Stripe's testing page says "The Stripe Services Agreement prohibits testing in live mode using real payment method details." Use its test values.
Test the sad paths as well as the happy path. Stripe's go-live checklist names incomplete data, invalid data and duplicate data. It also recommends having someone else test your integration.
Only test systems you own or have written permission to test. eSEOspace does not do penetration testing. If you need one, hire a qualified firm.
9. Go-live checks
Stripe's go-live checklist includes these items:
- Register live webhook endpoints, and confirm they work the same as your test ones.
- Confirm your production endpoint handles delayed and duplicate notifications.
- Make sure your code doesn't rely on test objects, because sandbox objects aren't usable in live mode.
- Rotate your keys in case they were saved outside your codebase during development.
- Make sure your code doesn't include any API keys.
- Review your logs, so they store only what you need and nothing sensitive.
Stripe's key guide says that when you rotate a key in the Dashboard, both old and new keys work for up to 7 days. Use that window, but finish the move.
10. Know where card data goes
Stripe's security guide says "PCI compliance is a shared responsibility and applies to both Stripe and your business."
It says some models that handle card numbers directly might need to meet more than 300 security controls. It also says many business models don't need to handle sensitive card data. They can use Stripe's low-risk integrations, so card details never pass through your servers.
The check. Confirm that card fields are Stripe's own hosted components, and not custom inputs that send numbers to your code. A qualified reviewer should confirm what your business must attest to each year.
Quick checklist
| Check | Done? |
|---|---|
No sk_ or rk_ key in frontend code or repository history | |
No secret in a VITE_ or NEXT_PUBLIC_ variable | |
| Webhook verifies signature against the raw body | |
| Fulfillment triggered by webhook, payment status confirmed | |
| Duplicate events create one order | |
| Handler doesn't depend on event order | |
| Amounts set on the server | |
| Live endpoint registered, keys rotated | |
| Card details collected by Stripe's components |
Next step
Work through this list in your sandbox before you launch. Then read the full AI-built app security checklist for the rest of the app.
If you'd like a second set of eyes, our website security consulting covers assessments of your setup. It reduces risk, but it cannot certify an app as safe, and we do not do penetration testing.
Frequently asked questions
Is it safe that my Stripe key shows in the browser?
It depends on the key. Stripe says publishable keys are safe to expose. Secret and restricted keys are not.
What does webhook signature verification do?
It confirms that an event really came from Stripe. Without it, Stripe says an attacker could send fake events that trigger fulfillment or account access.
Why did my webhook signature check start failing?
Stripe says any change to the raw request body causes verification to fail. Check whether your framework is parsing the body before your handler runs.
Can I give access on the success page?
Not on its own. Stripe says it's not guaranteed customers reach that page, and your server should confirm payment before granting anything.
Can I test with my own real card?
No. Stripe says its Services Agreement prohibits testing in live mode with real payment details. Use a sandbox and test values.











