paypath-api PR #47 feat/stripe-webhook-v2
[NEW] T01 Critical
Webhook secret not validated — HMAC spoofing via forged Stripe events
Spoofing Observed
The /api/webhooks/stripe endpoint processes incoming
Stripe events without validating the Stripe-Signature
header against the webhook secret. An attacker can POST forged
events to trigger payment state transitions — including marking
invoices as paid — without a valid Stripe signature.
Remediation: Validate every incoming webhook with
stripe.webhooks.constructEvent(body, sig, secret)
before processing. Return HTTP 400 on signature failure.
[NEW] T02 High
Payment amount tampered client-side before server validation
Tampering Observed
The amount field is set in the browser and passed to
/api/payments/create without re-deriving it from the
server-side cart. A user can intercept and modify the request to
pay an arbitrary amount, including zero.
Remediation: Derive payment amount server-side from the authenticated session's cart state. Treat all client-supplied amounts as untrusted input.
[NEW] T03 High
Replay attack — no idempotency key enforced on /api/payments
Repudiation Observed
Payment requests to /api/payments do not require or
validate an idempotency key. Replaying a captured valid request
will create duplicate charges. Under high network latency or retry
logic, this can cause double-billing.
Remediation: Require a client-generated
Idempotency-Key header on all payment creation requests.
Store keys with a TTL; reject duplicate keys within the window.
[NEW] T04 Medium
Error responses leak internal payment processor details
Info Disclosure Inferred
Payment failure responses include raw error objects from the Stripe SDK, exposing internal field names, stack trace fragments, and processor-specific error codes to the client.
Remediation: Catch Stripe errors server-side and return normalised error responses. Log full error detail server-side only. Never forward raw SDK exceptions to the client.