PolyShell Hardening Guide: Community Patches and WAF Rules
Sansec recorded 471 Magento stores compromised in one hour on March 30, 2026. Most editorial guides still point to a patch deprecated weeks ago. Adobe has not shipped a production fix. This is the corrected hardening path your hosting team can run today.
Key Takeaways
- PolyShell is an unauthenticated remote code execution flaw (CVE-2025-20720, CVSS 9.8) in Magento 2's REST API, affecting every production version through 2.4.8.
- Adobe has not shipped a production-branch patch. The fix arrives in Magento 2.4.9 GA on May 12, 2026.
- Mark Shust's original community patch is deprecated. The current recommendation is the aregowe module with eight interception layers.
- WAF rules from JeroenBoersma's NGINX gist block the attack at the edge before it reaches PHP.
- Sansec recorded 471 stores compromised in one hour on March 30, 2026 and 56.7% of vulnerable stores targeted within days.
- File-integrity monitoring catches post-exploit
accesson.phpbackdoors before customer fraud reports surface. - A managed-hosting layer with WAF deployment, PHP execution restriction in media directories, and IR playbooks closes the gap until 2.4.9 GA.
What Is PolyShell?
PolyShell = An unauthenticated remote code execution flaw in Magento 2's REST API guest-cart endpoint (CVE-2025-20720, CVSS 9.8 Critical). Polyglot files bypass Magento's image-content validator. Adobe has not shipped a production patch.
Affected: Every production version of Magento 2 through 2.4.8.
Mitigations now: aregowe community module, NGINX/Cloudflare WAF rules, file-integrity monitoring.
PolyShell exploits one endpoint: /rest/default/V1/guest-carts/:cartId/items. When a product option uses type file, the API accepts a file_info object containing base64-encoded data, a MIME type, and a filename. Magento validates the upload through getimagesizefromstring. A polyglot file passes that check and lands as PHP on disk. The technical mechanics are documented in Sansec's primary research and Searchlight Cyber's deep-dive.
Files upload to pub/media/custom_options/quote/. From there, attackers chain to remote code execution where PHP execution is permitted in that directory. Where it is not, attackers fall back to stored cross-site scripting through SVG and HTML payloads. Both classes are unauthenticated.
Sansec disclosed PolyShell on March 17, 2026. Adobe's response was silence on production branches. The fix exists in Magento 2.4.9 alpha3 and carries forward to 2.4.9 GA on May 12, 2026. APSB25-94 covered the fix in pre-release, but APSB26-05, the April 2026 quarterly patch, does not contain it. There is no production-branch backport on the Adobe release schedule.
The naming captures the attack class. Polyglot files are valid in two formats at once: a JPEG with embedded PHP, an SVG with executable script. PolyShell weaponizes that property against an endpoint Magento ships unauthenticated by design.
How Attackers Pair PolyShell With SVG Skimmers
A second Sansec post on April 7, 2026 documented a Magecart campaign targeting 99 Magento stores. The mechanism reads like a checklist of post-PolyShell persistence.
Attackers inject a 1x1 pixel SVG into the storefront with an onload handler. The handler runs base64-encoded JavaScript through setTimeout. The payload sits dormant until a customer clicks any checkout-related button. Then a full-screen "Secure Checkout" modal renders, complete with real-time Luhn validation on card numbers.
Captured card data is XOR-encoded with the key script, base64-encoded again, and exfiltrated to /fb_metrics.php on six domains. All six resolve to a single IP at 23.137.249.67 in the Netherlands, hosted by IncogNet LLC.
Sansec's research notes the initial compromise vector for this campaign was "likely PolyShell" but stops short of definitive attribution. The pairing logic stands either way. PolyShell delivers code execution on the storefront. SVG skimmers turn that execution into ongoing card theft. One exploits the upload, the other exploits the checkout.
For a hosting team, the operational implication is direct. Detection cannot stop at file-system signatures. SVG payloads live in product images, CMS blocks, and theme files. Hardening the upload path is necessary. It is not sufficient.
The Correct Community Patch in 2026 (aregowe over Deprecated Shust)
Mark Shust's magento-polyshell-patch was the first public mitigation. It worked as an interim hotfix while Sansec held disclosure. The README now carries one line that breaks every existing PolyShell guide on the open web:
"This package has been deprecated and abandoned in favor of
aregowe/magento2-module-polyshell-protection."
The aregowe module shipped v1.3.4 on April 23, 2026. Its composer.json includes a replace directive for the Shust package. Existing installations migrate without manual unwinding. This pattern is part of the broader security patch process that mature Magento operations follow when community-led mitigations supersede first-version hotfixes.
composer require aregowe/magento2-module-polyshell-protection
bin/magento module:enable Aregowe_PolyshellProtection
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
Composer recognizes the replace directive and removes the old Shust package without manual steps. No composer remove is needed. No code conflicts surface, because aregowe owns the same plugin slots.
The aregowe module ships eight interception layers. Each one fails closed under different attack permutations:
- Request-path blocking at the controller dispatch level for the guest-cart upload endpoint
-
Controller-level upload prevention that rejects the
file_infopayload before it reaches the framework's file-write logic -
Polyglot file detection that scans uploaded bytes for embedded PHP, SVG
onload, and HTML script tags -
Framework-level image hardening that wraps
Magento\Framework\Imageto enforce stricter MIME and extension checks -
REST API option-type filtering that blocks
type=fileon guest-cart endpoints regardless of product configuration - Filename normalization that strips traversal sequences before the file reaches disk
-
Disk-write deny on the quote directory that prevents new files from landing in
pub/media/custom_options/quote/ - Logging hooks that emit structured events on every interception for downstream alerting
A third community option exists: taurus-media/module-polyshell-fix. It uses a narrower interception model and ships fewer layers. No editorial coverage compares the three modules. The aregowe module is the version that the deprecated Shust README directs to, and it is the version with the most active maintenance footprint.
For self-managed stores, install aregowe today. For managed hosting, the question is whether the provider has already deployed the equivalent protection at the infrastructure layer. The next two sections address that.
WAF and NGINX Mitigations You Can Deploy Today
Module-level protection is one half of the answer. The other half lives at the request layer, before traffic reaches PHP. JeroenBoersma published an NGINX gist on April 9, 2026 that captures the operator-grade response.
The gist blocks two patterns. First, POST and PUT requests to /V1/guest-carts/[cartId]/items. Second, every request to /media/custom_options/. Both return 403 before the request enters the Magento backend.
The implementation uses NGINX map directives keyed on request method, request URI, and remote address. The 403 response is returned by NGINX. No PHP-FPM cycle, no Magento dispatch overhead. Quoted from the gist:
map "${request_method} ${request_uri}" $polyshell_block {
default "0";
"~*^(POST|PUT) /rest/.*?/V1/guest-carts/[^/]+/items" "1";
"~*^GET /media/custom_options/" "1";
}
server {
if ($polyshell_block = "1") {
return 403;
}
# ... rest of server block
}
For Cloudflare-fronted stores, the equivalent custom rule reads:
(http.request.method in {"POST" "PUT"} and
http.request.uri.path matches "^/rest/.*?/V1/guest-carts/[^/]+/items$") or
(http.request.uri.path contains "/media/custom_options/")
Set the action to Block. Order the rule above any positive-allow rules for REST. The WAF runs before origin, which means even a fully unpatched Magento instance never sees the malicious payload.
ModSecurity operators can mirror the same pattern with two SecRules:
SecRule REQUEST_METHOD "@rx ^(POST|PUT)$" \
"id:9000901,phase:1,deny,status:403,t:none, \
chain"
SecRule REQUEST_URI "@rx ^/rest/.*?/V1/guest-carts/[^/]+/items" \
"t:none"
SecRule REQUEST_URI "@rx ^/media/custom_options/" \
"id:9000902,phase:1,deny,status:403,t:none"
Apache stores running .htaccess can use a tighter rule for the media directory:
<LocationMatch "^/media/custom_options/">
Require all denied
</LocationMatch>
The trade-off is documented. Blocking the guest-cart upload endpoint disables product file-upload options for guest checkouts. Stores that sell printed merchandise, custom embroidery, or design-upload products lose that flow until they patch through the module path or upgrade to 2.4.9. Most stores never use guest file uploads. The WAF rule is appropriate by default. Disable it after the patch path is in place.
Detection: Are You Already Compromised?
Hardening assumes the attacker has not landed yet. For most production Magento stores, that assumption is no longer safe. BleepingComputer reported on March 25, 2026 that 56.7% of vulnerable stores were targeted within days of disclosure. A defensive deployment without a compromise check is half a response.
Sansec's free eComscan tool covers the file-system half. It scans Magento installations for known PolyShell payload patterns, the accesson.php backdoor signatures, and a broader catalog of post-exploitation persistence files. Run it against the document root. If the scan returns hits in pub/media/custom_options/quote/ or any web-accessible directory, treat the store as compromised and move to incident response. Detection is one pillar of Magento security best practices that pair with hardening to keep stores out of the next mass-exploitation wave.
Manual signature checks reinforce the automated scan:
# 1. List recent files in the upload landing zone
find pub/media/custom_options/ -type f -mtime -90 -ls
# 2. Look for the post-exploit backdoor name
find . -name "accesson.php" -type f -ls
# 3. Search for the SVG skimmer signature in CMS blocks
grep -r "fb_metrics.php" app/ pub/ var/ 2>/dev/null
# 4. Check the database for injected blocks
mysql -e "SELECT * FROM cms_block WHERE content LIKE '%onload%setTimeout%' OR content LIKE '%23.137.249.67%';"
Web-server log signatures complete the picture. NGINX access logs that show POST requests to /V1/guest-carts/.../items with non-zero response bodies and 200 status codes are candidate exploitation events. ModSecurity audit logs show the same pattern with full request bodies.
Stores running file-integrity monitoring (Tripwire, OSSEC, Wazuh) catch new file creation in the media directory in real time. Without FIM, the first signal a hosting team gets is when the skimmer payload lights up a customer fraud report.
If signatures fire, isolate the store, snapshot the file system, rotate every credential the application can reach (database, search, cache, payment gateway, admin), and rebuild from a known-good base before bringing traffic back. Patching a compromised store does not remove the persistence.
Managed-Hosting Posture Checklist
A managed hosting layer is the difference between two scenarios. In the first, the merchant patches their own application and trusts that no other surface is exposed. In the second, the hosting layer enforces hardening that no application-level patch can compromise. Ask any provider these questions:
- Is a WAF rule for the PolyShell endpoint deployed across every managed Magento store? Reference the JeroenBoersma gist patterns. A provider that says "we ship WAF" without the rule is not running the rule.
-
Is PHP execution disabled in
pub/media/? This is the one configuration that converts every PolyShell upload from RCE to harmless dropped files. The canonical NGINX pattern islocation ~ ^/media/.*\.php$ { deny all; }. -
Does file-integrity monitoring cover the document root? Real-time alerts on new file creation in
pub/media/custom_options/quote/catch the attack inside the exploit window, not after. -
Is image MIME-type allowlisting enforced at the infrastructure layer? Allowlist patterns reject polyglots before Magento ever runs
getimagesizefromstring. - Is there an incident-response playbook for unauthenticated RCE in Magento, with rotation timelines under 60 minutes? A playbook on paper is a starting point. A playbook with documented runs and post-mortems is operational.
- Are admin sessions, payment gateway tokens, and database credentials rotated automatically on suspected compromise? Manual rotation under incident pressure misses tokens.
- Are NGINX configurations versioned and audited? A WAF rule that lives in one operator's head disappears the day they leave.
- What is the SLA for emergency security-config deployment? Hours, days, or weeks materially change the breach window.
A provider that answers eight of eight is operating at the right tier. Six of eight is acceptable on a fast-track to closing the gaps. Below that, the merchant carries risk that the marketing copy does not name. Stores that need a hosting layer running this posture today can review managed Magento hosting for what we run on every store.
Adobe Patch Status: Why You Cannot Wait for the Production Backport
Adobe's bulletin schedule is public. APSB25-94 published October 14, 2025 covered multiple Commerce CVEs unrelated to PolyShell, plus the PolyShell fix itself, but only in the 2.4.9 pre-release branch. APSB26-05 in April 2026 shipped patches for 2.4.8-p4, 2.4.7-p9, 2.4.6-p14, and 2.4.5-p16. None of those production releases contain the PolyShell fix.
There is no announced backport. Adobe's stated position routes merchants to 2.4.9 GA on May 12, 2026. That date arrives 12 days from this writing. For stores running 2.4.6 or 2.4.5 lines that are not on the GA upgrade track, the timeline stretches further.
The reasoning is pragmatic. The PolyShell fix touches the cart custom-options upload pipeline. That code path interacts with quote-handling logic that has shifted across point releases. A clean backport would require regression coverage on every supported line. Adobe judged the upgrade path cleaner. Merchants pay for that judgment in additional exposure days.
The practical outcome is binary. Either upgrade to 2.4.9 GA on or near the May 12, 2026 release, or carry the vulnerability with module-level and infrastructure-level mitigations until you do. Both paths are valid. Doing neither is not. The 2.4.9 GA upgrade checklist walks through the full pre-flight sequence. The aregowe module, the WAF rules, and the FIM signatures cover the bridge. Use both, and document which mitigations are removed when the GA upgrade lands.
What This Means for Your Magento Stack Going Forward
PolyShell is the second high-severity Magento RCE in six months. SessionReaper (CVE-2025-54236) hit in October 2025 with a similar mass-exploitation profile. The pattern is now well-documented. Sansec, Searchlight Cyber, V-Formation, and BleepingComputer disclose. A community module ships within days. Adobe takes weeks to months to backport. WAF and infrastructure mitigations close the gap.
The operating model that survives this cadence treats the application as one layer in a defense stack, not as the perimeter. WAF rules are deployed as standard. File-integrity monitoring runs across every managed store. Community module evaluation is part of the security review process, not a reaction to disclosure. Incident response runs in hours, not days.
For stores still running 2.4.6 or 2.4.5 lines, the structural question is not whether to patch PolyShell. It is whether the upgrade cadence keeps pace with the disclosure cadence. The answer for most production stores is no. That gap is what managed hosting is for. The same response model applies as in October's disclosure: our SessionReaper hardening guide covers the parallel CVE-2025-54236 case with the same operating-model logic.
The merchants who absorb the next disclosure with no business interruption will be the ones who built this layer before they needed it.
FAQ
What is PolyShell in Magento?
PolyShell is an unauthenticated remote code execution vulnerability in Magento 2's REST API. It is tracked as CVE-2025-20720 with a CVSS score of 9.8 Critical. Attackers upload polyglot files through the guest-cart endpoint that bypass Magento's image validator and execute as PHP on the server. Every production version through 2.4.8 is affected.
Is my Magento store vulnerable to PolyShell?
Yes, if the store runs any production version of Magento 2 from the original release through 2.4.8. The fix is in Magento 2.4.9, which reaches GA on May 12, 2026. No production-branch backport has been released for 2.4.6, 2.4.7, or 2.4.8. Run Sansec's eComscan tool against the document root to confirm whether the store has been exploited.
What is the correct community patch for PolyShell?
The aregowe module at github.com/aregowe/magento2-module-polyshell-protection. Mark Shust's original patch is now deprecated and routes installations to aregowe through a Composer replace directive. The aregowe module ships eight interception layers and reached v1.3.4 on April 23, 2026.
Should I use the Mark Shust patch or the aregowe module?
Use aregowe. The Shust README marks the original package as deprecated and abandoned. Composer migrates existing Shust installations to aregowe through a replace directive. Most editorial guides written before April 2026 still reference the Shust patch and have not been updated.
Can WAF rules block PolyShell exploitation?
Yes. NGINX, Cloudflare, ModSecurity, and Apache can block POST and PUT requests to /V1/guest-carts/[cartId]/items and all access to /media/custom_options/. The JeroenBoersma NGINX gist provides a working rule. WAF rules run before the request reaches PHP, so even unpatched Magento instances are protected at that layer.
What is APSB25-94?
APSB25-94 is Adobe's October 14, 2025 quarterly security bulletin for Commerce. It covers multiple unrelated CVEs and includes the PolyShell fix in the 2.4.9 pre-release branch. The bulletin was not created for PolyShell. Researchers retroactively linked PolyShell to this bulletin when Sansec disclosed in March 2026.
Will Adobe ship a production-branch patch for PolyShell?
No announced backport exists. APSB26-05, the April 2026 quarterly release, did not include the fix for 2.4.5, 2.4.6, 2.4.7, or 2.4.8. Adobe's stated position routes merchants to the 2.4.9 GA upgrade on May 12, 2026.
How do I detect if my Magento store has been exploited?
Run Sansec's eComscan against the document root. Search for accesson.php files, recent files in pub/media/custom_options/quote/, and CMS blocks containing fb_metrics.php or external SVG onload handlers. Check NGINX logs for POST requests to the guest-cart endpoint with 200 responses and non-zero bodies.
What is the difference between PolyShell and SessionReaper?
SessionReaper (CVE-2025-54236) targets session storage and authentication. PolyShell (CVE-2025-20720) targets the REST API file upload. Both are unauthenticated and pre-auth. They affect different code paths and require different mitigations. Both are active in the wild as of April 2026.
Does GraphQL have the same vulnerability as PolyShell?
No. PolyShell is specific to the REST API guest-cart endpoint. GraphQL implementations do not expose the same file_info upload pattern. Stores that disabled REST but kept GraphQL active are not exposed to PolyShell. They remain exposed to other Magento RCE classes through different vectors.
Conclusion
Sansec recorded 471 stores compromised in one hour on March 30, 2026. V-Formation puts the vulnerable population at 112,000 to 130,000 storefronts. Adobe has not shipped a production patch. Most editorial coverage still routes readers to a deprecated module.
The corrected path runs three layers in parallel: install the aregowe community module today, deploy the WAF rules before traffic reaches PHP, and monitor the file system for the post-exploit signatures. None of those are theoretical. All three are running in production at hosting providers that take Magento security as an operational discipline. If the current hosting layer does not, what proper hardening looks like at the hosting layer describes the alternative.