{"id":"GHSA-6955-hrm5-c4qp","aliases":["CVE-2026-53638"],"title":"Sylius: Channel-based payment method restriction bypass on shop account orders API endpoint","description":"### 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)","severity":"medium","score":4.3,"published":"2026-07-09T21:03:46.000Z","modified":"2026-07-09T21:26:41.702Z","withdrawn":false,"knownExploited":false,"affected":[{"ecosystem":"Packagist","name":"sylius/sylius","ranges":[{"events":[{"introduced":"2.0.0"},{"fixed":"2.0.18"}],"type":"ECOSYSTEM"}],"versions":["v2.0.0","v2.0.1","v2.0.10","v2.0.11","v2.0.12","v2.0.13","v2.0.14","v2.0.15","v2.0.16","v2.0.17","v2.0.2","v2.0.3","v2.0.4","v2.0.5","v2.0.6","v2.0.7","v2.0.8","v2.0.9"],"fixed":["2.0.18"]},{"ecosystem":"Packagist","name":"sylius/sylius","ranges":[{"events":[{"introduced":"2.1.0"},{"fixed":"2.1.15"}],"type":"ECOSYSTEM"}],"versions":["v2.1.0","v2.1.1","v2.1.10","v2.1.11","v2.1.12","v2.1.13","v2.1.14","v2.1.2","v2.1.3","v2.1.4","v2.1.5","v2.1.6","v2.1.7","v2.1.8","v2.1.9"],"fixed":["2.1.15"]},{"ecosystem":"Packagist","name":"sylius/sylius","ranges":[{"events":[{"introduced":"2.2.0"},{"fixed":"2.2.6"}],"type":"ECOSYSTEM"}],"versions":["v2.2.0","v2.2.1","v2.2.2","v2.2.3","v2.2.4","v2.2.5"],"fixed":["2.2.6"]}],"references":["https://github.com/Sylius/Sylius/security/advisories/GHSA-6955-hrm5-c4qp","https://github.com/Sylius/Sylius"],"sources":[{"name":"OSV","id":"GHSA-6955-hrm5-c4qp","modified":"2026-07-09T21:26:41.702727Z","url":"https://osv.dev/vulnerability/GHSA-6955-hrm5-c4qp"}],"assessments":[{"source":"OSV","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N","score":4.3}]}