[Security] Honor-system payment confirmation: no Swish money verification on guest /pay endpoint #18

Open
opened 2026-06-22 11:11:51 +00:00 by hermes · 0 comments
Collaborator

Context

Identified during advisory review of #17 (guest checkout).

Problem

POST /api/guest-orders/{token}/pay is public (no JWT) and confirmGuestPayment simply transitions PENDING_PAYMENT -> PROCESSING without verifying that any Swish payment was received. The flow is: create order (no auth) -> get guest_token in response -> POST /pay -> order is now PROCESSING and heads to fulfillment (triggers notifyOrderProcessing).

A guest can mark an order paid without paying, and BilHej eats the PostNord cost for a free letter. The existing authenticated confirmPayment has the same honor-system design (acknowledged Phase 0), but the guest path removes account-level traceability and is fully anonymous.

Severity

Critical

Suggested fix

  • Tier 1: integrate Swish Commerce API + mTLS payment-verification callback so the backend only flips PROCESSING after a verified PAID callback.
  • Interim guard: place self-confirmed guest orders into a distinct pending_review status visible in admin tooling rather than PROCESSING, so fulfillment is gated on manual confirmation.

References

## Context Identified during advisory review of #17 (guest checkout). ## Problem `POST /api/guest-orders/{token}/pay` is public (no JWT) and `confirmGuestPayment` simply transitions `PENDING_PAYMENT -> PROCESSING` without verifying that any Swish payment was received. The flow is: create order (no auth) -> get `guest_token` in response -> POST `/pay` -> order is now `PROCESSING` and heads to fulfillment (triggers `notifyOrderProcessing`). A guest can mark an order paid without paying, and BilHej eats the PostNord cost for a free letter. The existing authenticated `confirmPayment` has the same honor-system design (acknowledged Phase 0), but the guest path removes account-level traceability and is fully anonymous. ## Severity Critical ## Suggested fix - Tier 1: integrate Swish Commerce API + mTLS payment-verification callback so the backend only flips `PROCESSING` after a verified `PAID` callback. - Interim guard: place self-confirmed guest orders into a distinct `pending_review` status visible in admin tooling rather than `PROCESSING`, so fulfillment is gated on manual confirmation. ## References - PR: https://srvr.nu/git/jocke/bilhej/pulls/17
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: jocke/bilhej#18
No description provided.