Payment operations are idempotent
Why it matters
Network errors and client retries are normal in distributed systems. Without idempotency keys, a retry after a timeout can create two Stripe Payment Intents for the same purchase — charging the customer twice. CWE-362 (Race Condition) and ISO 25010 functional-correctness both apply. Stripe's idempotency key mechanism guarantees that if you send the same key twice, you get the same response without creating a second charge — but you must opt in explicitly on every payment initiation call.
Severity rationale
Medium because duplicate charges are recoverable via refund but cause customer trust damage, support burden, and potential chargeback risk.
Remediation
Pass an idempotency key on every Stripe payment initiation call. Tie the key to the specific purchase intent so retries within a session return the existing object rather than creating a new one.
// Stable idempotency key: user + price + minute-level timestamp
// Minute-level granularity: allows retries within the same intent window
// but a new attempt a minute later gets a fresh key (new purchase intent)
const idempotencyKey = `checkout-${userId}-${priceId}-${Math.floor(Date.now() / 60000)}`
const session = await stripe.checkout.sessions.create(
{
customer: customerId,
line_items: [{ price: priceId, quantity: 1 }],
mode: 'subscription',
success_url: `${baseUrl}/billing/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${baseUrl}/pricing`,
},
{ idempotencyKey }
)
Alternatively, check for an existing incomplete checkout session in your database before creating a new one, and return the stored session URL on retry.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Billing & Payments Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- iso-25010:2011 · functional-correctness — Functional Correctness — payment operations produce correct outcomes under retry/network-error conditions
- cwe · CWE-362 — Concurrent Execution Using Shared Resource with Improper Synchronization (Race Condition)
Taxons
History
- 2026-04-18·v1.0.0·Initial import from saas-billing·automated