Decline codes are logged internally but not exposed to the client
Why it matters
Stripe's decline_code field on a StripeCardError carries values like stolen_card, fraudulent, card_velocity_exceeded, and insufficient_funds. If your API forwards this code to the browser, you are giving card-testing bots a real-time oracle: they can distinguish cards that are blocked as stolen from cards that are simply declined for insufficient funds, and continue probing with the latter. CWE-209 (Information Exposure Through Error Message) and CWE-200 (Exposure of Sensitive Information) both apply. OWASP A05 (Security Misconfiguration) covers this as information leakage. The internal decline_code is a legitimate signal for your fraud team — it should flow to your logging pipeline, not to the client.
Severity rationale
Medium because exposing decline codes to clients gives card-testing bots a free oracle to distinguish stolen-and-blocked cards from valid-but-declined ones, improving attack efficiency.
Remediation
Log the decline_code server-side for your fraud and support teams, and return a single generic message regardless of the specific decline reason.
} catch (err) {
if (err instanceof Stripe.errors.StripeCardError) {
// Internal: log the specific code for fraud pattern analysis
console.error('Card declined', {
decline_code: err.decline_code, // 'stolen_card', 'insufficient_funds', etc.
code: err.code,
paymentIntentId,
})
// External: generic message regardless of decline reason
return NextResponse.json(
{ error: 'Your payment was declined. Please contact your card issuer or try a different card.' },
{ status: 402 }
)
}
}
Do not map specific decline codes to user-facing messages like "Insufficient funds" — that narrows the attack surface for carding bots by confirming the card number is valid.
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 Payment Security Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-209 — Generation of Error Message Containing Sensitive Information
- cwe · CWE-200 — Exposure of Sensitive Information to an Unauthorized Actor
- owasp:2021 · A05
Taxons
History
- 2026-04-18·v1.0.0·Initial import from ecommerce-payment-security·automated