Can you add Stripe safely to a vibe-coded app?
By Seth Tucker · Updated June 2026
Yes — but only if the Stripe secret key never appears in the browser, checkout is created on the server (not the client), and webhooks are validated using the webhook signing secret before your app acts on them. These are the three non-negotiable requirements. A founder publicly reported that exposed Stripe keys in his vibe-coded app led to 175 customers being charged $500 each and $2,500 in Stripe fees. The correct setup prevents exactly that.
The documented risk: what happens when it goes wrong
In a case reported publicly and covered by Kiplinger and LinkedIn, a founder's vibe-coded startup was exploited after its Stripe secret key was placed in the frontend. The result: 175 customers charged $500 each, plus $2,500 in Stripe fees — all from a single exposed credential.
This is not a story about Stripe being unsafe. Stripe is one of the most carefully designed payment platforms available. It is a story about a key being placed in the wrong location. The fix is specific and well-documented. This article covers each piece of it.
The five things to get right
1. The publishable key vs the secret key
Stripe gives you two keys:
- The publishable key (
pk_live_...orpk_test_...): designed for use in the browser. It can create payment tokens and initialize the Stripe Elements UI. It cannot create charges, process refunds, or access customer data on its own. This key can be in your frontend code.
- The secret key (
sk_live_...orsk_test_...): must only be used in server-side code. It can create charges, create subscriptions, issue refunds, access your customer list, and modify any aspect of your Stripe account. If this key is in the browser, anyone who reads it has those same capabilities.
Check: open your app in a browser, right-click, choose Inspect, go to the Network tab, reload the page. Search for sk_live or sk_test. If you find either string, that is the secret key. Rotate it immediately from the Stripe dashboard (Developers then API keys then Roll secret key) and move it to your builder's server-side environment.
2. Server-side checkout creation
There are two ways to use Stripe for accepting payments. One is safe. One is not.
The correct way: when a user clicks "pay," your frontend sends a request to your own server. Your server uses the Stripe secret key to create a PaymentIntent or Checkout Session. Stripe returns an ID or URL. The frontend uses that ID or URL to complete the payment using Stripe's own hosted flow or Stripe Elements. The secret key never leaves the server.
The problematic way: the frontend directly calls Stripe's API using the secret key to create a PaymentIntent. This means the secret key must be in the browser for the call to work. Any AI that generates this pattern has placed the credential in the wrong location.
If you are not sure which pattern your app uses, open the Network tab while clicking through a payment and look at which URLs the requests go to. Requests to api.stripe.com directly from the browser using the secret key indicate the problematic pattern. Requests to your own app's server, which then calls Stripe, indicate the correct pattern.
3. Webhook validation
Stripe sends webhook events to your server to notify you about payment outcomes: a payment succeeded, a subscription renewed, a charge was disputed. These are the signals your app uses to actually grant access, send confirmation emails, and record revenue.
Webhooks are HTTP requests sent to a URL you configure. Anyone who knows that URL can send requests to it — not just Stripe. Without validation, your app might grant access or record revenue in response to a fake webhook event.
Stripe's solution: a webhook signing secret (whsec_...). Every real webhook from Stripe is signed with this secret. Your server verifies the signature before acting on the event. If the signature does not match, the request is not from Stripe and should be ignored.
Check: find the webhook handling code in your app and look for a signature verification step. In Stripe's own libraries, this is typically stripe.webhooks.constructEvent(payload, signature, webhookSecret) or equivalent. If the webhook handler does not include this step, it will accept fake events.
The webhook signing secret must be stored server-side — it is as sensitive as the Stripe secret key.
4. Test mode before live
Stripe provides a complete test environment. Test keys (pk_test_... and sk_test_...) process no real money and carry no real financial risk. Use test mode exclusively until the payment flow works correctly end-to-end.
| Check | What to verify |
|---|---|
| Test keys in development | All development and staging environments use pk_test_ and sk_test_ credentials only |
| Live keys only in production | pk_live_ and sk_live_ appear only in the production environment's server-side configuration |
| Test mode indicator | In the Stripe dashboard, you can see whether you are viewing test mode or live mode data; confirm the payment events you expect to see actually appear in the test mode log |
| Test card numbers | Stripe provides test card numbers (4242 4242 4242 4242 is the most common) that trigger successful payments in test mode without any real charge |
| Webhook testing | Use Stripe's webhook testing tools in the dashboard or the Stripe CLI to send test events to your webhook endpoint and verify that your app responds correctly |
5. Fraud controls and rate limits
Once your Stripe integration is live, two additional controls protect you from abuse:
Spending limits: Set alerts (and, where possible, caps) in Stripe's dashboard for unusual volume. An endpoint that allows someone to trigger payment operations at scale — for example, by submitting a payment form many times in rapid succession — can create chargebacks and processing fees before you notice.
Rate limiting on payment endpoints: Your app should limit how many payment-related requests a single user or IP address can make in a given time period. AI-generated code rarely includes this by default. OWASP API Security (API4:2023) covers unrestricted resource consumption and recommends rate limits on operations that have a cost per call.
Stripe Radar: Stripe's built-in fraud detection runs automatically. Review the Radar settings in your Stripe dashboard to confirm the default rules are active and appropriate for your use case.
Quick-reference: safe vs needs attention
| Item | Safe | Needs attention |
|---|---|---|
| Stripe secret key location | Server-side only, in environment variables | Visible in the browser network tab — rotate immediately |
| Stripe publishable key location | In the frontend code — expected | Not applicable |
| Checkout/PaymentIntent creation | Happens on your server | Happens directly from the browser using the secret key |
| Webhook validation | Signature verified using whsec_ secret before any action is taken | No signature verification — handler accepts any HTTP request |
| Test vs live keys | Test keys in all non-production environments; live keys only in production server | Live keys in development or test environments, or test keys in production |
| Spend limits and rate limits | Configured and tested | Not configured |
What to ask an expert
Payment integration review is one of the highest-value things to get a second opinion on before you charge real customers. The questions worth bringing:
- Is my Stripe secret key exclusively in server-side code and absent from the browser?
- Are PaymentIntents or Checkout Sessions created on my server, not in the browser?
- Does my webhook handler verify the Stripe signature before acting on events?
- Are my test and live keys correctly separated across environments?
- Do I have rate limits on payment-related endpoints, and are Stripe Radar's default rules active?
If you would like AgentC to review your Stripe integration before you accept real payments, the right starting point is a demo conversation. We check the key placement, the checkout flow, the webhook validation, and the rate limiting — and tell you plainly what is ready and what needs work before you go live.
Related guides in this series
- Is your AI-built app safe to put in front of customers? (the pillar guide) — the full triage
- Did the AI put your API keys in the wrong place? How to check and what to rotate
- You already shipped and now you are worried: a 60-minute containment plan
- What should you ask an expert to audit in your AI-built app?
- Production-ready vs demo-good: the vibe-coding reality check
Frequently asked questions
Is the Stripe publishable key safe to have in my app's frontend?
Yes. The publishable key is designed for browser use — it can initialize Stripe Elements and tokenize card details, but it cannot create charges, issue refunds, or access customer data on its own. It is safe to be visible in your frontend code and in the browser's network tab. The Stripe secret key is the one that must never appear in the browser.
My app uses a no-code tool like Bubble or Webflow for payments. Does this apply?
It depends on how the tool integrates with Stripe. If the tool uses a pre-built Stripe integration where the payment processing happens through the tool's platform (not your own server-side code), the tool's implementation is the one to review — specifically, whether it is using the publishable or secret key client-side. Consult the tool's documentation for its Stripe integration model and confirm that the secret key is managed by the platform, not embedded in any custom code you wrote.
What if the AI generated the Stripe integration incorrectly? Can I ask it to fix it?
Yes. You can describe the correct pattern to the AI — secret key server-side only, PaymentIntents created on the server, webhook signature validation included — and ask it to rewrite the relevant parts. The important step after the rewrite is verification: re-run the network tab check to confirm the secret key no longer appears in the browser, and use Stripe's webhook testing tools to confirm validation is active. The rewrite and the verification are both necessary.
What is the webhook signing secret, and where do I find it?
The webhook signing secret (whsec_...) is a separate credential from your Stripe API keys. You find it in your Stripe dashboard under Developers then Webhooks. After you add or select a webhook endpoint, Stripe reveals a signing secret specific to that endpoint. This secret must be stored in your server-side environment (not the frontend) and used in your webhook handler to verify that incoming requests are genuinely from Stripe. Each webhook endpoint has its own signing secret — if you have multiple endpoints, each has a different one.
Should I set spending limits even if my app is small?
Yes. Spending limits on Stripe are not about doubting your users — they are about limiting the financial impact of an unexpected event, whether that is unauthorized API access, a software bug that triggers duplicate charges, or a fraudulent actor who finds a vulnerability. Setting an alert at an amount that would be unusual for your app's normal volume costs nothing and provides early warning. It is one of the fastest risk reductions available.
About this guide
Written by Seth Tucker, founder of AgentC Consulting. Seth spent approximately five years as a security engineer on election infrastructure used by roughly one in three American voters, holds SOC 2 Type 2 and ISO 27001 experience, and now helps non-technical founders and operators build, review, and trust AI-built applications.
Last updated: June 2026. Sources cited throughout reference original research, vendor documentation, and public reporting.
More than vibes
Want a second set of eyes on your app?
The right starting point is a demo conversation, not a form. We look at what you built, ask the questions that matter for your situation, and tell you plainly what is safe to ship and what needs work first.