PT-2026-44439 · Packagist · Shopper/Cart

Publicado

2026-05-18

·

Atualizado

2026-05-18

CVSS v3.1

5.9

Média

VetorAV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N

Impact

CreateOrderFromCartAction::execute previously created the Order row before checking and incrementing the discount's total use counter. Under concurrent checkout pressure (Black Friday, flash sale, viral coupon), the global usage limit was silently exceeded: orders were committed with the discount fully applied to price amount while the counter blocked at usage limit. The merchant had no signal that an over-redemption had occurred.
A second related bug: usage limit per user was effectively a no-op because the counter it relied on (DiscountDetail.total use) was never incremented anywhere in the codebase. The per-user check therefore always saw 0 uses and validation passed regardless of how many times the same customer had previously redeemed the coupon. For eligibility = Everyone the per-user limit could not fire at all because the underlying DiscountDetail row only exists for eligibility = Customers.
Direct financial loss: each over-redemption is a discount the merchant did not intend to grant.

Patches

Fixed in v2.8.0. CreateOrderFromCartAction now:
  • Reserves the discount slot atomically before the order row is created, inside the same DB::transaction with lockForUpdate and a compare-and-swap on total use.
  • Throws DiscountLimitReachedException::global and rolls back the transaction when the global limit was exhausted between cart validation and commit. No order is committed.
  • Throws DiscountLimitReachedException::perUser and rolls back when the discount is restricted to one use per customer and the customer has already redeemed it.
  • Snapshots discount id, discount code, discount type, discount value at apply and discount currency code onto the orders table for resilience against later discount edits or deletions.
DiscountValidator was updated to perform the same Order-based per-user check at cart-apply time so the rejection is surfaced before checkout.
Upgrade via:
composer require shopper/cart:^2.8 shopper/core:^2.8 php artisan migrate

Workarounds

None. Upgrade to v2.8.0.

Resources

Correção

Race Condition

Encontrou algum problema na descrição? Tem algo a acrescentar? Fique à vontade para nos escrever 👾

Enumeração de Fraquezas

Identificadores relacionados

GHSA-9RH9-HF3W-9FGG

Produtos afetados

Shopper/Cart