VDB
Sign up
MEDIUM6.5

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.0

Details

## 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

Packagist/shopper/framework
Introduced in: 0Fixed in: 2.9.0
Fixcomposer require shopper/framework:^2.9.0

References