CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-23498
7.20.06%

Shopware Twig RCE: Bypassing Security with a PHP Array

Alon Barad
Alon Barad
Software Engineer

Feb 19, 2026·5 min read·11 visits

PoC AvailableCISA KEV Listed

Executive Summary (TL;DR)

A type-juggling flaw in Shopware's Twig `map` filter allowed attackers to bypass the function allow-list by passing a PHP array callable instead of a string. This leads to RCE.

Shopware, a popular e-commerce platform, contained a critical Remote Code Execution (RCE) vulnerability in its Twig template security extension. The flaw arose from a regression in how the `map` filter validated PHP callbacks. While the developers diligently implemented an allow-list to block dangerous functions like `system` or `exec` when passed as strings, they failed to account for PHP's flexible type system, which allows callables to be passed as arrays (e.g., `[ClassName, MethodName]`). This oversight allowed attackers with template editing privileges to bypass the security check entirely, executing arbitrary code on the server.

The Hook: When Security Extensions Aren't Secure

Shopware is the backbone of thousands of European e-commerce stores. It handles credit cards, PII, and order history. To give frontend developers flexibility, Shopware exposes Twig, the standard PHP template engine. Twig is generally safe because it's sandboxed—you can't just write <?php system('rm -rf /'); ?> inside a template. It won't parse.

However, developers often need to transform data, so Shopware added the map filter. This acts just like PHP's native array_map, taking a list of items and a function to apply to them. Because map accepts a callback, it is inherently dangerous. If you let a user map system over an array of user input, you get RCE.

Shopware knew this. They wrote a SecurityExtension to act as a bouncer, checking every function passed to map against a strict allow-list. But as every hacker knows, bouncers can be distracted. In this case, the bouncer was only looking for people wearing nametags (strings), completely ignoring the group of people holding hands (arrays).

The Flaw: PHP's Type System is a Weapon

The root cause of CVE-2026-23498 is a classic case of "assuming the input type." In PHP, a callable—something you can execute—comes in many shapes. It can be a simple string (e.g., 'strtoupper'), an anonymous function (Closure), or an array representing a method call (e.g., ['MyClass', 'myMethod']).

The vulnerability lived in src/Core/Framework/Adapter/Twig/SecurityExtension.php. The developers wrote a check that looked essentially like this:

> "If the function name is a string, check if it is in the allowed list. If not, throw an error."

Do you see the logic gap? If the function is not a string—say, an array—the if block is skipped entirely. The code falls through to the return statement, which happily passes the unchecked array callable to array_map. PHP doesn't care that you skipped the security check; it just executes the method. This is like locking your front door but leaving the garage door wide open because "only cars go in there."

The Code: The Smoking Gun

Let's look at the actual code diff. This is where the magic happens. The vulnerable code explicitly relied on is_string to trigger the security validation.

// VULNERABLE CODE (Pre-6.7.6.1)
public function map(?iterable $array, string|callable|\Closure $function): ?array
{
    // ... (irrelevant code)
 
    // THE BUG: strict check for string type
    if (\is_string($function) && !\in_array($function, $this->allowedPHPFunctions, true)) {
        throw AdapterException::securityFunctionNotAllowed($function);
    }
 
    // If $function was an array, we arrive here safely.
    return array_map($function, $array);
}

If an attacker passes ['SomeDangerousClass', 'pwn'], is_string returns false. The security exception is never thrown. array_map receives the array, sees it is a valid callable, and executes SomeDangerousClass::pwn().

The fix (Commit 3966b05) forces the input into a normalized string format before checking it:

// PATCHED CODE
if (\is_array($function)) {
    // Normalize array callables to 'Class::Method' strings
    $function = implode('::', $function);
    \assert(\is_callable($function));
}
 
// Now the check runs regardless of input type
if (\is_string($function) && !\in_array($function, $this->allowedPHPFunctions, true)) {
    throw AdapterException::securityFunctionNotAllowed($function);
}

The Exploit: Crafting the Payload

To exploit this, we need access to edit a Twig template. This is common in Shopware for administrators or developers who can modify email templates, CMS blocks, or document configurations. We need to find a static method in the codebase that allows command execution or file writing, or simply leverage a gadget chain.

While standard PHP functions like system are strings, PHP allows calling static methods via arrays. An attacker would hunt for a class available in the autoloaded scope that accepts a string argument and does something interesting.

Conceptual Attack Chain:

  1. Identify Entry Point: The attacker edits the "Order Confirmation" email template.
  2. Inject Payload: instead of {{ customer.firstName }}, they inject:
    {# Bypass the string check by using an array #}
    {{ ['id'] | map(['\Shopware\Core\System\SystemConfig\SystemConfigService', 'set']) }}
    (Note: This is a hypothetical gadget; a real attacker would look for exec wrappers or file writers).
  3. Trigger: The attacker places a test order. The email template renders.
  4. Execution: array_map executes the static method. The server is compromised.

Even without a direct exec gadget, simply calling internal Shopware methods that modify database state or configuration can lead to privilege escalation or persistent backdoors.

The Impact: From Template to Shell

This is a Critical severity issue for a reason. RCE allows an attacker to completely takeover the host operating system. In the context of an e-commerce platform, this is catastrophic.

  • Data Exfiltration: The attacker can dump the entire MySQL database, stealing customer addresses, order history, and hashed passwords.
  • Payment Skimming: They can modify the JavaScript files served by the storefront to capture credit card details in real-time (Magecart style).
  • Persistence: They can install a web shell or a persistent cron job to maintain access even after the vulnerability is patched.

The only mitigating factor is the requirement for high privileges (access to Twig templates). However, in many organizations, "marketing" staff have access to CMS/Email templates but should not have the ability to execute code on the server.

The Fix: Normalization is Key

The remediation is straightforward: Update to Shopware 6.7.6.1. The patch doesn't just block arrays; it normalizes them. By converting ['Class', 'Method'] into the string 'Class::Method', the code ensures that the allow-list logic is applied universally.

If you cannot patch immediately (why?), you can attempt to mitigate this by locking down the permissions of users who can edit templates. Ensure that no untrusted accounts have access to the Mail Template or CMS editors.

For security researchers and developers, the lesson is clear: Never rely on type checks for security boundaries in loosely typed languages. Always normalize input to a known state before validation.

Official Patches

ShopwareOfficial patch on GitHub
ShopwareSecurity Advisory

Fix Analysis (1)

Technical Appendix

CVSS Score
7.2/ 10
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
0.06%
Top 80% most exploited
15,000
Estimated exposed hosts via Shodan

Affected Systems

Shopware 6.7.0.0Shopware 6.7.1.0Shopware 6.7.2.0Shopware 6.7.3.0Shopware 6.7.4.0Shopware 6.7.5.0Shopware 6.7.6.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
Shopware
Shopware
>= 6.7.0.0, < 6.7.6.16.7.6.1
AttributeDetail
CWE IDCWE-863 (Incorrect Authorization)
Attack VectorNetwork (Authenticated)
CVSS v3.17.2 (High)
EPSS Score0.06%
ImpactRemote Code Execution (RCE)
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059.003Command and Scripting Interpreter: Windows Command Shell
Execution
T1059.004Command and Scripting Interpreter: Unix Shell
Execution
CWE-863
Incorrect Authorization

The system performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. In this case, type juggling allows bypassing the check.

Known Exploits & Detection

MetasploitNo official module yet, but easily constructible via Twig injection.
GitHubAdvisory with reproduction steps.
NucleiDetection Template Available

Vulnerability Timeline

Fix committed to Shopware repository
2026-01-05
CVE-2026-23498 published
2026-01-14
Added to CISA KEV
2026-01-20

References & Sources

  • [1]GitHub Security Advisory
  • [2]NVD Entry
  • [3]PHP Manual: Callables
Related Vulnerabilities
CVE-2023-2017

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.