T09 · Insecure Skill Coding Practices
- Location
SKILL.md:136- Finding
Timestamp-Based Checkout Idempotency Key Allows Duplicate Checkout Sessions
- Content
View full analysis
; }) { const session = await stripe.checkout.sessions.create({ customer: params.customerId, mode: params.mode, line_items: [{ price: params.priceId, quantity: 1 }], success_url: `${params.successUrl}?session_id={CHECKOUT_SESSION_ID}`, cancel_url: params.cancelUrl, metadata: params.metadata ?? {}, // Recommended defaults allow_promotion_codes: true, billing_address_collection: 'auto', tax_id_collection: { enabled: true }, customer_update: { address: 'auto', name: 'auto' }, payment_method_types: ['card'], // For subscriptions ...(params.mode === 'subscription' && { subscription_data: { metadata: params.metadata ?? {}, trial_period_days: 14, }, }), }, { idempotencyKey: `checkout_${params.customerId}_${params.priceId}_${Date.now()}`, }); return session; } ``` ### Technical Analysis Stripe idempotency only works when every retry of the same logical operation uses exactly the same idempotency key. Incorporating `Date.now()` creates a different key each time the function is invoked. Consequently, Stripe treats retries as independent requests rather than returning the result of the original request. The key also lacks a stable order or transaction identifier. Two legitimate purchases of the same price by the same customer cannot be distinguished using business-operation identity, while retries cannot be reliably correlated with the original request. This directly conflicts with the Skill's stated requirement that all mutating API calls be idempotent. ### A ...[truncated 1159 chars]- Remediation
View remediation
