
SonicWall Capture Labs threat research team became aware of the threat CVE-2026-75650, assessed its impact, and developed mitigation measures. The flaw, also known as StyleSmuggler, is a critical vulnerability affecting Adobe Commerce, Adobe Commerce B2B, and Magento Open Source. It lets an unauthenticated attacker run arbitrary code on a store by smuggling a template directive through the styles parameters of the storefront API. That directive drives Magento's template filter into instantiating an attacker-named class whose constructor passes a caller-supplied path to include, which executes any PHP it finds there. Classified under CWE-1336 (Improper Neutralization of Special Elements Used in a Template Engine) and rated CVSS 10.0 (Critical) with the vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H, it was discovered by Sansec and fixed by Adobe on September 7, 2026 in APSB26-146 (hotfix VULN-39341). It had already been exploited as a zero day for about three days. CISA added it to the Known Exploited Vulnerabilities catalog on September 8, 2026 with a remediation due date of September 11, 2026. Its EPSS score of 3.95% places it in the 90th percentile. Adobe lists fixes for Adobe Commerce 2.4.4 through 2.4.9, Adobe Commerce B2B 1.3.3 through 1.5.3, and Magento Open Source 2.4.4 through 2.4.9; older releases are out of support and receive no official patch. Administrators should apply the hotfix immediately, then rotate the encryption key and every credential it protects, because patching does not undo a compromise that already happened.
Adobe Commerce and Magento Open Source are the commercial and open-source editions of the same e-commerce platform. Both render transactional email and CMS content through a template filter that reads directives in a double-brace syntax such as {{block}} and {{var}}. Email templates carry a companion template_styles value holding the CSS applied at render time. Those styles values are the smuggling channel the name refers to: presentation data that reaches machinery building live PHP objects.

The root cause is in the template filter's handling of deferred directives. In lib/internal/Magento/Framework/Filter/Template.php, once the filter has resolved the directives it found, it signs any directive whose rendered output is byte-identical to the directive text itself. The assumption is that such a directive is deferred and will be resolved later by a parent template, so it is safe to trust. An attacker-supplied directive that the filter simply cannot resolve satisfies exactly the same condition, so it is handed a valid signature and is then trusted when the parent template renders.

The signed directive is turned into objects by two factories that construct before they validate. BlockFactory::createBlock() calls create() on the attacker-named class, then tests the result with instanceof BlockInterface. By the time that check throws, the constructor and its side effects have already run.

The grid row URL generator factory reached by the same object graph repeats the pattern. UrlGeneratorFactory::createUrlGenerator() instantiates $generatorClassName before testing it against GeneratorInterface, so the resulting InvalidArgumentException reports what already happened rather than preventing it.

Arbitrary instantiation only matters if some reachable class does something dangerous in its constructor, and Magento ships one. The Zend/Laminas class map autoloader (ClassMapAutoloader), bundled as magento/zend-loader, forwards constructor options through setOptions(), registerAutoloadMaps(), and registerAutoloadMap() into loadMapFromFile(), where the caller-supplied path is handed to include. Naming this class and pointing its map file at any file containing PHP source therefore yields code execution entirely from the constructor, which is exactly the window the two factories leave open.

In the observed campaign the attacker first writes PHP to disk, then points the autoloader at it. Sansec documented PHP source injected through the query string of POST /paypal/transparent/response/, which lands in a crash report under var/report/, followed by a POST /graphql carrying the object graph in styles parameters with styles[first] pointing back at that report file. The attack then provokes Magento's "Payment Transaction Failed Reminder" message so the template, and with it the smuggled directive, renders.
APSB26-146 repairs both halves of the chain. BlockFactory and UrlGeneratorFactory now test the resolved type as a string with is_a($class, Interface::class, true) before anything is created, so a nonconforming class is rejected without its constructor running. The crash report writers prefix every report with <?php exit; ?> and rewrite <? to < ?, so an included report can no longer execute. The email and newsletter preview blocks gain the ADMIN_RESOURCE constant and isAllowed() check that 2.4.9 lacked. The signing logic in Filter/Template.php is left unchanged, so the trust decision at the root of the chain survives the patch, and variants reaching other include or require gadgets remain plausible.

The following conditions must be met for successful exploitation of CVE-2026-75650:
Exploiting CVE-2026-75650 requires no credentials, no tooling beyond an HTTP client, and no interaction from any user. The attack runs in three steps:
Nothing in the responses distinguishes any of this from normal storefront traffic, so detection has to key on the requests themselves.
Video Demonstration
| Component | Value | Purpose |
|---|---|---|
| Reconnaissance Probe | POST /graphql with PHP in the Store header | Confirms an unpatched target; reflected in an HTTP 200 GraphQL input error |
| Stage 1 Write | POST /paypal/transparent/response/ query string | Deposits PHP source into a crash report under var/report/ |
| Payload File | var/report/<sha256> | The file the autoloader is later instructed to include |
| Stage 2 Gadget | POST /graphql with styles[...] parameters | Describes the object graph the template filter will build |
| Instantiated Classes | styles[generatorClass], styles[second], styles[with_resolved][0][_i_] | Name the classes created through the unvalidated factories |
| Include Path | styles[first] set to a relative path under var/report/ | Supplies the map file path that reaches include |
| Execution Sink | ClassMapAutoloader::__construct() | Reaches include from the constructor, before any type check rejects it |
| Render Trigger | "Payment Transaction Failed Reminder" message | Forces the template, and the smuggled directive, to render |
| Server Response | HTTP 200 | A successful attack returns an ordinary status code, not a 4xx or 5xx |
To ensure SonicWall customers are prepared for any exploitation that may occur due to this vulnerability, the following signatures have been released:
| Signature ID | Signature Name |
|---|---|
| IPS: 22503 | Adobe Commerce PHP open tag in Store request header |
| IPS: 22504 | Adobe Commerce Store request header Command Execution |
| IPS: 22505 | Adobe Commerce Store header PHP payload Reflected in GraphQL |
The risks posed by CVE-2026-75650 can be mitigated or eliminated with the following measures:
The vulnerability was discovered by Sansec, which identified the active in-the-wild campaign on September 4, 2026 and reported it to Adobe. Adobe published the fix on September 7, 2026 in Security Bulletin APSB26-146 as hotfix VULN-39341, and extended patch coverage to Magento Open Source 2.4.4 and 2.4.5 on September 18, 2026.
Share This Article

An Article By
An Article By
Security News
Security News