critical

CVE

CVE-2026-75650

CWE

CWE-94

Affected Surface

  • Magento Open Source 2.4.7, 2.4.8, and 2.4.9, reproduced vulnerable in public reporting
  • Magento Open Source 2.4.6-p15 with July and August 2026 security updates applied, observed compromised in the wild
  • Adobe Commerce current supported releases now covered by Adobe's emergency `APSB26-146` / `VULN-39341` guidance
  • Headless and PWA storefronts that must keep GraphQL exposed to the internet
  • Linux hosts running Magento under unprivileged site users, where the post-exploitation implant persists through cron

StyleSmuggler remains the strongest application-security story from the last three days. Public reporting on 5 September showed active, unauthenticated exploitation against Magento Open Source, and Adobe has now confirmed the issue as CVE-2026-75650 with emergency bulletin APSB26-146 and hotfix VULN-39341. The attack matters because it does not look like a normal checkout bug. The public chain abuses a frontend input surface, crosses into Magento’s template and setup internals, and ends with server-side PHP execution plus a persistent Linux implant.

The vendor update closes the biggest uncertainty from the first 48 hours, but it does not make the incident routine. Stores that were exposed before the hotfix still need incident-response work, because the published post-exploitation behavior persists as the site user through cron and survives past the initial web request.

Affected projects and versions

The affected projects currently called out in public reporting are:

  • Magento Open Source 2.4.7, 2.4.8, and 2.4.9, where the full unauthenticated chain was reportedly reproduced on clean installs.
  • Magento Open Source 2.4.6-p15 with July and August 2026 security updates applied, where Sansec says the first known victim still showed a clean security:patch-status.
  • Adobe Commerce current supported releases, now formally addressed by Adobe’s APSB26-146 response and the VULN-39341 hotfix track.

The current evidence also suggests uneven operational impact by storefront model. Disrex’s incident follow-up says headless and progressive web app storefronts usually need GraphQL exposed, while many classic and Hyva storefronts can disable it temporarily with less business impact.

What the public chain currently supports

The clearest public description is Sansec’s two-stage outline:

POST /graphql?styles[...]=
  -> attacker poisons a file Magento later reads or renders
  -> a payment failure path triggers Magento's built-in failed-payment email
  -> Magento renders attacker-controlled PHP during email generation
  -> the dropper downloads and launches a Linux implant

Sansec also published these request shapes as indicators tied to observed attacks:

POST /graphql?styles[....]=
POST /paypal/transparent/response/?<?=eval(base64_decode('....
GET /customer/section/load/?sections=customer&force_new_section_timestamp=true

Those indicators are not the same thing as a full proof of concept. The exact chain is still partly opaque. Sansec said a fuller breakdown of the gadget chain and implant would follow later. The important point for defenders is simpler: real stores were compromised through an unauthenticated path before the vendor hotfix landed.

Why the failed-payment email matters in code

The failed-payment email is not a made-up execution sink. Magento really does generate it from checkout exception handling. In app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php, a localized exception path calls sendPaymentFailedEmail():

$this->_objectManager->get(\Magento\Checkout\Helper\Data::class)
    ->sendPaymentFailedEmail($this->getOnepage()->getQuote(), $e->getMessage());

Inside Magento\Checkout\Helper\Data, that helper builds a transactional email with template variables such as reason, items, billingAddressHtml, shippingAddressHtml, and paymentMethod:

$transport = $this->_transportBuilder->setTemplateIdentifier(
    $template
)->setTemplateOptions(
    [
        'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE,
        'store' => Store::DEFAULT_STORE_ID
    ]
)->setTemplateVars(
    [
        'reason' => $message,
        'checkoutType' => $checkoutType,

That is why Sansec’s description matters: if an attacker can poison content that later reaches transactional template rendering, the email path becomes an execution boundary worth treating as production code, not as a harmless notification.

The suspected DI compiler sink is plausible, and still unconfirmed

The most technical follow-up came from incident-response reporting tied to Disrex. Their read is that the chain eventually drives Magento code under setup/src/Magento/Setup/Module/Di/Code/, which exists to support dependency-injection compilation, into including attacker-chosen PHP from a poisoned path.

One public source file in that area, ClassesScanner.php, shows why defenders should take that theory seriously:

public function getList($path)
{
    $realPath = realpath($path);
    ...
    $recursiveIterator = new \RecursiveIteratorIterator(
        new \RecursiveDirectoryIterator($realPath, \FilesystemIterator::FOLLOW_SYMLINKS),
        \RecursiveIteratorIterator::SELF_FIRST
    );
    ...
    if (!class_exists($className)) {
        require_once $fileItemPath;
    }
}

If code meant for setup-time scanning becomes reachable in an HTTP execution path with attacker influence over $path or over the files inside it, require_once $fileItemPath; stops being harmless compiler plumbing and becomes a straight server-side code loading primitive.

That said, defenders should separate “plausible” from “confirmed.” Sansec had not confirmed the exact sink at publication time, and Disrex explicitly framed its own work as live incident-response analysis, not as a vendor-validated root cause. Treat public guards in this area as hardening layers, not as a complete fix.

Post-exploitation behavior on Linux hosts

Once the chain lands, the attacker does not stop at one PHP payload. Public reporting describes a small Rust implant that persists as the Magento site user, not as root. The process is disguised as a kernel worker:

process [kworker/u:8:0]
file    ~/.local/share/.gvfsd/gvfsd-user
cron    */5 * * * * exec <home>/.local/share/.gvfsd/gvfsd-user

That choice matters operationally:

  • A real kernel kworker thread is owned by root. A bracketed kworker owned by a site user is suspicious.
  • The implant sits outside the document root, so web-root-only scans can miss it.
  • Disrex reported a case where the running binary under /proc/<pid>/exe differed from the file on disk, so hashing only the file path is not enough.

Sansec published two sample hashes:

e315687a1dfe61ef4a5a5642214db6d3b2b05d81391285eebc2af664641a26a7
b79dfdc1eed860e0b76c629d6adfce251db379b0b45a6d728d4ef483f7551420

Follow-up reporting added more indicators, including direct cron-spool writes and extra source IPs. That is useful context, but it does not change the main response rule: hunt for the running process, the persistence path, and the poisoned Magento logs together.

Detection and hunting

Start with the Linux host, then pivot back into Magento logs and application behavior.

Look for the implant and persistence:

ps -eo user,pid,rss,comm,args | rg '\[kworker/u:8:0\]|gvfsd-user'
ls -la ~/.local/share/.gvfsd /tmp/.kw_* /tmp/.gvfsd-* 2>/dev/null
rg -n 'gvfsd-user|/tmp/.kw_' /var/spool/cron /var/spool/cron/crontabs 2>/dev/null

Look for poisoned files and execution markers in Magento-managed paths:

rg -n 'X[_-]?TRACE_|<\?=eval\(base64_decode|array_merge\(' var/report var/log/system.log

If you find a live process, hash both the on-disk file and the running executable:

sha256sum ~/.local/share/.gvfsd/gvfsd-user
sha256sum /proc/<pid>/exe

At the application layer, investigate any sudden burst of “Payment Transaction Failed” notifications, checkout exceptions that do not line up with normal payment-provider failures, and requests hitting /graphql with suspicious styles[...] parameters.

Official mitigation now that Adobe has shipped a fix

There is finally a vendor-backed primary action:

  1. Apply Adobe’s VULN-39341 hotfix for the exact Magento Open Source or Adobe Commerce branch you run.
  2. Verify the patch state before assuming the store is covered. Adobe’s own cloud guidance uses:
vendor/bin/magento-patches -n status | grep "39341\\|Status"
  1. Rotate the encryption key and any credentials that may have been readable from app/etc/env.php or from the site user’s environment. Adobe’s emergency guidance now makes that credential-rotation step explicit.
  2. If you cannot patch immediately, disable GraphQL if the storefront model allows it.
  3. If GraphQL must stay on, add temporary request filtering around known styles[...] abuse patterns and treat those rules as campaign-specific containment, not as a fix.
  4. Harden the host so a PHP dropper has fewer places to land. Public incident-response guidance specifically calls out proc_open and executable temporary directories.

Example containment steps to evaluate in staging first:

disable_functions = proc_open
tmpfs /tmp      tmpfs rw,nosuid,nodev,noexec 0 0
tmpfs /var/tmp  tmpfs rw,nosuid,nodev,noexec 0 0
tmpfs /dev/shm  tmpfs rw,nosuid,nodev,noexec 0 0

Several unofficial Magento hardening patches also appeared before Adobe published its response. They focus on preventing setup-time DI scanner paths from running under web requests or on blocking specific email-template and report-processing behaviors. They are now fallback hardening measures, not the primary remediation path. Public reporting already notes compatibility risk with some third-party modules, so treat them as temporary guards around the official hotfix, not a replacement for it.

Response priorities if compromise is suspected

If you suspect a store has already been hit:

  1. Preserve the process and filesystem evidence before cleaning aggressively.
  2. Remove persistence before killing the process, because the process may recreate the cron entry.
  3. Invalidate Magento sessions.
  4. Rotate Magento admin credentials, payment-provider secrets, integration keys, and any other credentials stored in app/etc/env.php or reachable from the site user.
  5. Rotate crypt/key and other encrypted application secrets in line with Adobe’s hotfix guidance if incident scoping suggests the attacker could read them.

Do not let a clean patch-status report lull you into delaying response. The first public victim already had current Adobe security updates for its release line. StyleSmuggler is a reminder that the exploitable boundary in a large PHP platform is often the space between subsystems: API input, templating, setup code, background email generation, and host-level persistence.

From research to remediation

Check whether this pattern exists in your codebase

Turn this research into a remediation workflow. Use AI-native static analysis to find similar application vulnerabilities and generate review-ready fixes.

References