{"id":"CVE-2026-53638","aliases":["GHSA-6955-hrm5-c4qp"],"url":"https://o3.security/vulnerability/CVE-2026-53638","summary":"Sylius: Channel-based payment method restriction bypass on shop account orders API endpoint","details":"### Impact\nAn authorization bypass vulnerability exists in the shop account API. The `PATCH /api/v2/shop/account/orders/{tokenValue}/payments/{paymentId}` endpoint, used by an authenticated shop customer to change the payment method of an order that has been placed but not yet paid (state `STATE_NEW`), does not validate that the chosen payment method is enabled for the order's channel. The equivalent checkout endpoint (`PATCH /api/v2/shop/orders/{tokenValue}/payments/{paymentId}`) correctly rejects out-of-channel payment methods with `HTTP 422`; the account endpoint silently accepts them and returns `HTTP 200`.\n\nAn authenticated customer can therefore assign any globally enabled payment method to their own placed order, including methods that the store operator has explicitly excluded from that channel. \n\n### Patches\nThe issue is fixed in versions: 2.0.18, 2.1.15, 2.2.6 and above.\n\n### Workarounds\nIf users cannot bump Sylius right now, decorate the `Sylius\\Bundle\\ApiBundle\\Changer\\PaymentMethodChangerInterface` service in their applications. \n\n#### Step 1. Create the decorator\n\n`src/Decorator/ChannelCheckingPaymentMethodChanger.php`:\n\n```php\n<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Decorator;\n\nuse ApiPlatform\\Validator\\Exception\\ValidationException;\nuse Sylius\\Bundle\\ApiBundle\\Changer\\PaymentMethodChangerInterface;\nuse Sylius\\Component\\Core\\Model\\OrderInterface;\nuse Sylius\\Component\\Core\\Model\\PaymentMethodInterface;\nuse Sylius\\Component\\Core\\Repository\\PaymentMethodRepositoryInterface;\nuse Sylius\\Component\\Core\\Repository\\PaymentRepositoryInterface;\nuse Sylius\\Component\\Payment\\Resolver\\PaymentMethodsResolverInterface;\nuse Symfony\\Component\\Validator\\ConstraintViolation;\nuse Symfony\\Component\\Validator\\ConstraintViolationList;\nuse Symfony\\Contracts\\Translation\\TranslatorInterface;\n\nfinal readonly class ChannelCheckingPaymentMethodChanger implements PaymentMethodChangerInterface\n{\n    public function __construct(\n        private PaymentMethodChangerInterface $decorated,\n        private PaymentRepositoryInterface $paymentRepository,\n        private PaymentMethodRepositoryInterface $paymentMethodRepository,\n        private PaymentMethodsResolverInterface $paymentMethodsResolver,\n        private TranslatorInterface $translator,\n    ) {\n    }\n\n    public function changePaymentMethod(string $paymentMethodCode, mixed $paymentId, OrderInterface $order): OrderInterface\n    {\n        /** @var PaymentMethodInterface|null $paymentMethod */\n        $paymentMethod = $this->paymentMethodRepository->findOneBy(['code' => $paymentMethodCode]);\n        $payment = $this->paymentRepository->findOneByOrderId($paymentId, $order->getId());\n\n        if (\n            $paymentMethod !== null\n            && $payment !== null\n            && !in_array($paymentMethod, $this->paymentMethodsResolver->getSupportedMethods($payment), true)\n        ) {\n            $template = 'sylius.payment_method.not_available';\n            $parameters = ['%name%' => (string) $paymentMethod->getName()];\n\n            throw new ValidationException(new ConstraintViolationList([\n                new ConstraintViolation(\n                    message: $this->translator->trans($template, $parameters, 'validators'),\n                    messageTemplate: $template,\n                    parameters: $parameters,\n                    root: $paymentMethodCode,\n                    propertyPath: '',\n                    invalidValue: $paymentMethodCode,\n                ),\n            ]));\n        }\n\n        return $this->decorated->changePaymentMethod($paymentMethodCode, $paymentId, $order);\n    }\n}\n```\n\n#### Step 2. Register the decorator\n\n`config/services.yaml` (append to the application's existing `services:` block):\n\n```yaml\nservices:\n    App\\Decorator\\ChannelCheckingPaymentMethodChanger:\n        decorates: sylius_api.changer.payment_method\n        arguments:\n            - '@.inner'\n            - '@sylius.repository.payment'\n            - '@sylius.repository.payment_method'\n            - '@sylius.resolver.payment_methods'\n            - '@translator'\n```\n\n`@.inner` references the original `PaymentMethodChangerInterface` implementation, so any future Sylius change to the changer keeps working through the decorator.\n\n#### Step 3. Clear the cache\n\n```bash\nbin/console cache:clear\n```\n\n### Reporters\n\nWe would like to extend our gratitude to the following individuals for their detailed reporting and responsible disclosure of this vulnerability:\n- Fredrik Dietrichson (@FredrikEV)\n\n### For more information\n\nIf there are any questions or comments about this advisory:\n\n- Open an issue in [Sylius issues](https://github.com/Sylius/Sylius/issues?q=sort%3Aupdated-desc+is%3Aissue+is%3Aopen)\n- Send an email to [security@sylius.com](mailto:security@sylius.com)","published":"2026-09-08T22:25:26.679Z","modified":"2026-10-28T02:31:04.134501925Z","cvss":{"score":4.3,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N"},"epss":{"score":0.00178,"percentile":0.07572,"asOf":"2026-09-17"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Packagist","name":"sylius/sylius","fixedVersion":"2.0.18"},{"ecosystem":"Packagist","name":"sylius/sylius","fixedVersion":"2.1.15"},{"ecosystem":"Packagist","name":"sylius/sylius","fixedVersion":"2.2.6"}],"fix":null,"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/53xxx/CVE-2026-53638.json"},{"type":"ADVISORY","url":"https://github.com/Sylius/Sylius/security/advisories/GHSA-6955-hrm5-c4qp"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-53638"},{"type":"PACKAGE","url":"https://github.com/Sylius/Sylius"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:31:04.134501925Z"}}