An order that was shipped yesterday cannot be cancelled the same way as an order placed five minutes ago. If the same code path applies to both, a customer can trigger a 'cancelled' transition on an already-shipped order — potentially generating an automated refund while the package is still in transit and arrives at the customer's door. This is a CWE-285 failure: the system grants a cancellation action to a user for an order state where that action should be restricted to admin review. Post-shipment cases require a separate branch: queue the request, notify the admin, and communicate a different resolution timeline to the customer.
Medium because a single undifferentiated cancellation path enables customers to cancel shipped orders with no admin oversight, creating refund and logistics conflicts.
Add a second branch to your cancellation handler at app/api/orders/[id]/cancel/route.ts that routes post-shipment requests to an admin review queue rather than auto-cancelling.
const POST_SHIPMENT = ['shipped', 'delivered']
if (POST_SHIPMENT.includes(order.status)) {
await db.cancellationRequests.create({
data: {
orderId: order.id,
userId: session.user.id,
requestedAt: new Date(),
status: 'pending_review',
reason: body.reason,
},
})
await sendAdminNotification({ type: 'post_shipment_cancellation', orderId: order.id })
return Response.json({
message: 'Request received. Our team will contact you within 1–2 business days.',
})
}
ID: ecommerce-order-management.cancellation-refunds.postshipment-cancellation
Severity: medium
What to look for: Check whether the cancellation logic explicitly distinguishes between pre-shipment and post-shipment orders. Count the number of distinct code branches handling cancellation for different order statuses. For orders that are already shipped or delivered, look for at least 1 of these special handling patterns: a separate endpoint or flow for post-shipment cancellation requests, a flag or queue entry that routes the request to an admin for approval, or a clear user-facing error message (quote the exact message if found) explaining that standard cancellation is not available. The key question is: does the system have at least 2 distinct branches — one for pre-shipment and one for post-shipment?
Pass criteria: The cancellation flow explicitly handles the post-shipment case differently from pre-shipment, with at least 2 distinct code branches. Shipped or delivered orders either cannot be cancelled through the standard customer path (with a helpful error message directing the customer to contact support or initiate a return) or enter a separate admin-approval queue. The system does not silently apply a standard cancellation to an already-shipped order. A single code path that treats all statuses identically does not count as pass.
Fail criteria: The cancellation handler treats all order statuses the same (only 1 code branch) — a shipped order can be cancelled through the exact same path as a pending order with no differentiation, no admin notification, and no flagging for special handling.
Skip (N/A) when: The project does not support post-shipment cancellations at all and clearly communicates this to customers at the time of purchase (e.g., "All sales are final once shipped"). Or the project delegates all post-shipment handling to an external returns management platform. The cancellation handler explicitly rejects all non-pre-shipment statuses.
Detail on fail: "The cancellation endpoint at POST /api/orders/[id]/cancel applies the same logic regardless of order status (1 code branch, 0 post-shipment guards). A shipped order can be cancelled by the customer with no admin notification or special handling."
Remediation: Add explicit post-shipment routing in your cancellation handler at app/api/orders/[id]/cancel/route.ts:
const POST_SHIPMENT_STATUSES = ['shipped', 'delivered']
if (POST_SHIPMENT_STATUSES.includes(order.status)) {
// Route to admin queue instead of auto-cancelling
await db.cancellationRequests.create({
data: {
orderId: order.id,
userId: session.user.id,
requestedAt: new Date(),
status: 'pending_review',
reason: body.reason,
},
})
// Notify admin
await sendAdminNotification({ type: 'post_shipment_cancellation_request', orderId: order.id })
return Response.json({
success: true,
message: 'Your cancellation request has been received and is under review. ' +
'Our team will contact you within 1-2 business days.',
})
}