GHSA-5vf4-452p-jjhf
Shopper: Negative discount values accepted and propagated through order calculation pipeline
Quick fix
GHSA-5vf4-452p-jjhf — shopper/framework: upgrade to the fixed version with the command below.
composer require shopper/framework:^2.9.0Details
## Summary
The Shopper Framework discount management functionality accepts negative discount values without server-side validation.
It was confirmed that negative fixed-amount discounts can be created through the administrative interface, persisted to the database, and subsequently processed by the cart/order calculation pipeline.
The application appears to assume that discount values are always positive but does not enforce this assumption during creation, storage, or calculation.
As a result, malformed discount records can influence financial calculations and produce unintended order totals.
---
## Affected Product
**Package:** shopper/framework
**Version Tested:** 2.8.1
---
## Vulnerability Type
* Business Logic Vulnerability * Improper Input Validation (CWE-20)
---
## Description
While reviewing the discount functionality, it was discovered that the application accepts negative discount values through the administrative interface.
Example values tested:
```text -50.00 -99,999,999.00 ```
The application accepted these values without validation and stored them in the database.
Example records observed in the `sh_discounts` table:
```text 1 | QCZ5Y3HESM | fixed_amount | -5000 4 | TOZKAHCB4S | fixed_amount | -9999999900 ```
This demonstrates that negative discount values are successfully persisted.
---
## Steps to Reproduce
### 1. Create a Discount
Login as an administrator.
Navigate to:
```text /cpanel/discounts ```
Create a new discount with the following values:
```text Type: fixed_amount Value: -99999999 ```
Save the discount.
### 2. Observe Successful Creation
The discount is accepted by the application and displayed in the administration interface.
Example:
```text Code: TOZKAHCB4S Amount: -$99,999,999.00 ```
### 3. Verify Database Persistence
Inspect the database:
```sql select * from sh_discounts; ```
Observed entry:
```text TOZKAHCB4S | fixed_amount | -9999999900 ```
---
## Technical Analysis
### Discount Calculation
File:
```text vendor/shopper/cart/src/Discounts/DiscountCalculator.php ```
Observed code:
```php $fixedAmount = $discount->value; ```
The value is later processed without validation:
```php $fixedAmount = min($fixedAmount, $applicableSubtotal); ```
When a negative value is supplied:
```php min(-9999999900, 10000) ```
returns:
```php -9999999900 ```
allowing the negative value to continue through the calculation pipeline.
The resulting adjustment values are inserted into the database:
```php CartLineAdjustment::query()->insert($adjustments); ```
No validation was identified to ensure that discount amounts are positive before calculations occur.
---
### Final Total Calculation
File:
```text vendor/shopper/cart/src/Pipelines/Calculate.php ```
Observed logic:
```php $context->total = max( 0, $context->taxInclusive ? $context->subtotal - $context->discountTotal : $context->subtotal - $context->discountTotal + $context->taxTotal ); ```
Because negative discount values are allowed to reach this stage, financial calculations are performed using malformed discount data.
Example:
```text Subtotal = 10000 DiscountTotal = -5000 ```
Resulting calculation:
```text 10000 - (-5000) ```
Result:
```text 15000 ```
This demonstrates that negative discount values directly affect order total calculations.
---
## Impact
The following was confirmed:
* Negative discount values are accepted. * Negative discount values are persisted. * Negative discount values are processed by the discount calculation engine. * Negative discount values affect order total calculations.
Potential consequences include:
* Incorrect pricing calculations. * Financial data integrity issues. * Unexpected order totals. * Violated assumptions within downstream pricing logic. * Future vulnerabilities if additional components assume discount values are always positive.
Because Shopper is a headless e-commerce administration framework and does not ship with a customer-facing storefront, it was not verified a customer-facing exploitation path.
However, malformed discount records currently propagate through pricing calculations without validation.
---
## Recommendation
Implement server-side validation enforcing positive discount values before persistence and before entering the calculation pipeline.
Suggested validation:
### Fixed Amount Discounts
```text value > 0 ```
### Percentage Discounts
```text 0 < value <= 100 ```
Additionally, existing discount records should be validated before calculation to prevent malformed data from influencing pricing logic.
---
## Environment
```text Shopper Framework 2.8.1 Laravel 12.61.1 PHP 8.4.16 SQLite ```
Are you affected?
Enter the version of the package you're using.
Affected packages
0Fixed in: 2.9.0composer require shopper/framework:^2.9.0