CVE-2022-23614 (PHP, published 2022-02-04T23:15Z)
Description: value: Twig is an open source template language for PHP. When in a sandbox mode, the `arrow` parameter of the `sort` filter must be a closure to avoid attackers being able to run arbitrary PHP functions. In affected versions this constraint was not properly enforced and could lead to code injection of arbitrary PHP code. Patched versions now disallow calling non Closure in the `sort` filter as is the case for some other filters. Users are advised to upgrade.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-94 \u2014 Improper Control of Generation of Code ('Code Injection')
The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
Repository: https://github.com/twigphp/Twig
Files changed:
CHANGELOG
src/Extension/CoreExtension.php
tests/Extension/SandboxTest.php
Commit message: Disallow non closures in `sort` filter when the sanbox mode is enabled


Vulnerable code:
# 2.14.11 (2022-XX-XX)
* n/a
* Allow more null arguments when Twig expects a string (for better 8.1 support)
            new TwigFilter('sort', 'twig_sort_filter'),
function twig_sort_filter($array, $arrow = null)
    if (!$arrow instanceof Closure && $env->hasExtension('\Twig\Extension\SandboxExtension') && $env->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed()) {
        throw new RuntimeError('The callable passed to "filter" filter must be a Closure in sandbox mode.');
    }
    if (!$arrow instanceof Closure && $env->hasExtension('\Twig\Extension\SandboxExtension') && $env->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed()) {
        throw new RuntimeError('The callable passed to the "map" filter must be a Closure in sandbox mode.');
    }
    if (!$arrow instanceof Closure && $env->hasExtension('\Twig\Extension\SandboxExtension') && $env->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed()) {
        throw new RuntimeError('The callable passed to the "reduce" filter must be a Closure in sandbox mode.');
    }
        $this->expectExceptionMessage('The callable passed to "filter" filter must be a Closure in sandbox mode in "index" at line 1.');

Fixed code:
# 2.14.11 (2022-02-04)
 * Fix a security issue when in a sandbox: the `sort` filter must require a Closure for the `arrow` parameter
 * Allow more null arguments when Twig expects a string (for better 8.1 support)
            new TwigFilter('sort', 'twig_sort_filter', ['needs_environment' => true]),
function twig_sort_filter(Environment $env, $array, $arrow = null)
        twig_check_arrow_in_sandbox($env, $arrow, 'sort', 'filter');

    twig_check_arrow_in_sandbox($env, $arrow, 'filter', 'filter');
    twig_check_arrow_in_sandbox($env, $arrow, 'map', 'filter');
    twig_check_arrow_in_sandbox($env, $arrow, 'reduce', 'filter');

function twig_check_arrow_in_sandbox(Environment $env, $arrow, $thing, $type)
{
    if (!$arrow instanceof Closure && $env->hasExtension('\Twig\Extension\SandboxExtension') && $env->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed()) {
        throw new RuntimeError(sprintf('The callable passed to the "%s" %s must be a Closure in sandbox mode.', $thing, $type));
    }
}
        $this->expectExceptionMessage('The callable passed to the "filter" filter must be a Closure in sandbox mode in "index" at line 1.');