NewN-Day-BenchView benchmark
winfunc
Back to Hacktivity

Status: Patched

This vulnerability has been verified as resolved and deployed.

Sylius logo
SyliusHigh2026-09-02

Captured payment can be reused after cart total inflation

Summary

Cart recalculation rewrote a payment already claimed by the gateway

A guest could capture a legitimate low amount, enlarge the same mutable order, and have Sylius mark the enlarged order paid while the payment provider had captured only the original amount.

Root cause. OrderPaymentProcessor rewrote the amount and currency of the last cart-state payment whenever the order total changed, even after a capture or authorization request had handed that payment to a gateway. The later status flow trusted the gateway's success state but did not reconcile the captured amount.

Remediation evidence. Sylius published GHSA-vv4h-q2x8-74g4 with an explicit Winfunc Research credit and fixed the invariant in releases 2.1.16 and 2.2.9 by preventing claimed payments from being rewritten or removed.

CVSS Score

VectorN
ComplexityL
PrivilegesN
User InteractionN
ScopeU
ConfidentialityN
IntegrityH
AvailabilityN
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

Vulnerability Location

SourceLine 25
src/Sylius/Bundle/ApiBundle/Command/Payment/AddPaymentRequest.php
AddPaymentRequest::__construct()
SinkLine 70
src/Sylius/Bundle/PayumBundle/Action/CapturePaymentAction.php
CapturePaymentAction::execute()

Source-to-Sink Analysis

1
src/Sylius/Bundle/ApiBundle/Resources/config/api_platform/resources/shop/PaymentRequest.xml:37

A guest starts a gateway capture for an inexpensive, attacker-owned cart payment.

PYTHON
POST /api/v2/shop/orders/{token}/payment-requests
{ "paymentId": 7, "action": "capture" }
2
src/Sylius/Component/Core/OrderProcessing/OrderPaymentProcessor.php

After a successful low-value capture, cart recalculation overwrites the same local payment with the enlarged order total.

PYTHON
$payment->setAmount($order->getTotal());
$payment->setCurrencyCode($order->getCurrencyCode());
3
src/Sylius/Bundle/PayumBundle/Action/StatusPaymentAction.php

The gateway reports the earlier transaction captured, and Sylius completes the rewritten payment without comparing the provider amount.

PYTHON
if ($status->isCaptured()) {
  $stateMachine->apply($payment, 'complete');
}

Impact Analysis

Critical Impact

The store can fulfill goods or other paid value worth more than the provider actually captured. The confirmed impact is payment/order integrity failure and underpayment fraud; service availability and data confidentiality are unaffected.

Attack Surface

Guest or customer checkout on Sylius 2.x stores using a capture-capable Payum gateway and the Payment Request API.

Preconditions

The attacker controls their own cart and a valid low-value payment instrument. The merchant must have a capture/status-capable gateway enabled; no victim account or callback forgery is needed.

Proof of Concept

Environment Setup

Use an isolated affected Sylius 2.x store with a capture-capable test Payum gateway and one inexpensive product.

Target Configuration

Enable the shop Payment Request API and normal guest checkout. Use provider test credentials only.

Exploit Delivery

Capture the initial cart total, increase item quantity on the same cart, complete checkout, then process a status request for the original gateway transaction.

Outcome

In 2.1.16 and 2.2.9, payments already claimed by a gateway are not rewritten; the enlarged order requires a distinct correctly valued payment.

Expected Response: The order reaches paid for the enlarged total while the gateway ledger shows only the original smaller capture.

Run this level of analysis on your repo.

Winfunc traces source-to-sink paths, validates exploitability, and gives your team patch-ready remediation.

Vulnerability Detection