Commit Graph

641 Commits

Author SHA1 Message Date
Fabien Potencier 8d6af0707b Fix sandbox __toString bypass via the in and not in operators 2026-05-27 14:52:32 +02:00
Fabien Potencier cc1e21a2a2 Fix sandbox __toString bypass via Traversable in join/replace filters 2026-05-27 14:52:30 +02:00
Fabien Potencier afbaa2a9da Mark new SourcePolicyInterface column filter tests as @group legacy
These tests pass a SourcePolicyInterface instance to SandboxExtension, which
triggers the 3.27 deprecation. Mark them legacy and assert the deprecation
to silence the PHPUnit "unhandled deprecation" report.
2026-05-27 14:49:53 +02:00
Fabien Potencier 09c6706407 Fix sandbox bypass in the "column" filter under SourcePolicyInterface 2026-05-27 14:49:52 +02:00
Fabien Potencier af7bf5e181 Add a strict mode to SecurityPolicy to opt-in to the 4.0 sandbox behavior for the extends/use tags and the parent/block/attribute functions 2026-05-25 13:40:27 +02:00
Fabien Potencier cfaa2fd030 Deprecate the fact that the parent, block, and attribute functions are always allowed in a sandboxed template 2026-05-24 21:19:56 +02:00
Fabien Potencier 33690a4a28 Fix PHP 8.1+ implicit float-to-int deprecation in sandboxed array access 2026-05-24 17:39:37 +02:00
Fabien Potencier e235cae3a1 Fix sandbox bypass in deprecated internal wrappers 2026-05-24 11:10:36 +02:00
Fabien Potencier f6aca309d8 Escape root profile name in HtmlDumper 2026-05-23 09:39:26 +02:00
Fabien Potencier 4c1dae5e71 Restrict allowed classes in Profile::unserialize() 2026-05-23 09:09:19 +02:00
Fabien Potencier 4fc0210084 Bump version 2026-05-23 08:32:22 +02:00
Fabien Potencier bd924d5d33 Deprecate the "Twig\Sandbox\SourcePolicyInterface" interface 2026-05-23 08:30:05 +02:00
Fabien Potencier 0a80d1a9aa Remove Drupal integration tests 2026-05-22 12:38:21 +02:00
Fabien Potencier a0a1f1d17d Replace FQCN with use statements in SandboxTest 2026-05-22 12:08:11 +02:00
Fabien Potencier 4a64b5b486 Fix CS 2026-05-21 16:34:23 +02:00
Fabien Potencier 3190b9ae12 Pre-escape HTML input on the spaceless filter 2026-05-20 08:29:48 +02:00
Alexandre Daubois f05c5011c2 Fix sandbox bypass in the "column" filter 2026-05-20 07:33:52 +02:00
Fabien Potencier 2e4b6d286e security #cve-2026-47732 [Sandbox] Fix __toString() support (fabpot)
This PR was merged into the twig-3.x branch.
2026-05-20 07:31:34 +02:00
Fabien Potencier 3464990a51 security #cve-2026-47730 [Profiler] Escape template and profile names in HtmlDumper (nicolas-grekas)
This PR was merged into the twig-3.x branch.
2026-05-20 07:31:01 +02:00
Fabien Potencier 447d0b2331 Fix sandbox __toString bypasses 2026-05-20 00:18:59 +02:00
Fabien Potencier ea3f7a2844 Validate macro name in MacroReferenceExpression constructor
The name passed to MacroReferenceExpression is emitted as raw PHP in
compile() via "->{$name}(...)". Callers were expected to validate
the name, but a missing check led to CVE-2026-XXXXX (PHP code injection
via _self / import macro reference): defense-in-depth, validate the
name in the constructor so the class is safe by construction.
2026-05-19 23:42:31 +02:00
Alexandre Daubois 324fa60545 Fix sandbox bypass: PHP code injection via _self / import macro reference 2026-05-19 23:41:59 +02:00
Fabien Potencier aeb37f4801 Fix deprecations in tests 2026-05-19 23:05:30 +02:00
Alexandre Daubois 819c6a89fe Fix sandbox bypass in the {% sandbox %} tag when including a preloaded template 2026-05-19 23:00:58 +02:00
Fabien Potencier 679447fa29 Encode single quotes as \x27 in Compiler::string()
This is a defense-in-depth measure: callers must always concatenate the
result into a double-quoted PHP context, but if one ever (mistakenly)
embeds it inside a single-quoted PHP literal, an attacker-controlled
single quote in the source value could break out of that context. The
previous commit fixed exactly such a bug in ModuleNode for the {% use %}
template name.

Encoding ' as the hex escape \x27 guarantees that the emitted PHP source
never contains a literal single quote derived from user input, while the
decoded runtime value is unchanged. \' is not used because it is not a
recognized escape sequence in PHP double-quoted strings (the backslash
would be kept literally).
2026-05-19 22:58:27 +02:00
Alexandre Daubois e9ff55f691 Fix sandbox bypass: PHP code injection via {% use %} template name 2026-05-19 22:50:45 +02:00
Fabien Potencier e494400ce4 Fix deprecation 2026-05-19 22:05:26 +02:00
Fabien Potencier a8eb5a8a74 security #cve-2026-46639 Fix sandbox bypass in object destructuring assignment (alexandre-daubois)
This PR was merged into the twig-3.x branch.
2026-05-19 21:37:04 +02:00
Fabien Potencier c8dfd62064 security #cve-2026-24425 Fix sandbox bypass: propagate Source to checkArrow for source-policy sandboxing (fabpot)
This PR was merged into the twig-3.x branch.
2026-05-19 21:30:51 +02:00
Nicolas Grekas a5f6e8793e [Profiler] Escape template and profile names in HtmlDumper
The HtmlDumper output is intended to be rendered in a browser, and the
template and macro/block names it interpolates are loader-controlled
(e.g. the key for ArrayLoader or a database row id), so they can carry
arbitrary HTML when an application stores templates under user-supplied
identifiers.
2026-05-19 18:54:32 +02:00
Fabien Potencier fd0760d972 feature #4795 Lazy load EscaperRuntime in EscaperExtension (GromNaN)
This PR was merged into the 3.x branch.

Discussion
----------

Lazy load `EscaperRuntime` in `EscaperExtension`

This allows overriding `EscaperRuntime` via a custom runtime loader.

Previously, `EscaperExtension::setEnvironment()` was calling `$environment->getRuntime(EscaperRuntime::class)` eagerly. Since this method is called from `Environment::__construct()`, the runtime was resolved before any custom runtime loader could be injected, making it impossible to override `EscaperRuntime`.

- Required by https://github.com/symfony/symfony/pull/63929

Commits
-------

b73ab8cfd9 Lazy load EscaperRuntime in EscaperExtension
2026-05-17 07:52:38 +01:00
Fabien Potencier d0579ededc Fix sandbox bypass: propagate sandbox state to checkArrow for source-policy sandboxing 2026-05-16 18:56:08 +01:00
Fabien Potencier 5462817da0 Add a needs_is_sandboxed option for filters, functions, and tests 2026-05-16 18:52:17 +01:00
itsalmostchristmas 2b4aa4458a Make embeds deterministic 2026-05-16 09:48:23 +01:00
Jérôme Tamarelle b73ab8cfd9 Lazy load EscaperRuntime in EscaperExtension
Previously, setEnvironment() called getRuntime(EscaperRuntime::class) eagerly,
which prevented overriding EscaperRuntime via a custom runtime loader since
Environment::__construct() calls setEnvironment() before any loader can be injected.
2026-04-30 13:43:11 +02:00
Alexandre Daubois 3fe13f98f8 Fix sandbox bypass in object destructuring assignment 2026-04-28 12:59:06 +02:00
Fabien Potencier e56cdfdded bug #4778 Fix null coalescing operator with imported macros (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Fix null coalescing operator with imported macros

Closes #4776

When using the null coalescing operator with a macro imported via the `from` tag, the `TemplateVariable` node inside `MacroReferenceExpression` was deep-cloned, causing the clone to generate a different `$macros` key than the one assigned by `AssignTemplateVariable`. This resulted in a `Call to a member function hasMacro() on null` error.

Commits
-------

efa004caab Fix null coalescing operator with imported macros
2026-02-25 10:38:36 +01:00
Fabien Potencier efa004caab Fix null coalescing operator with imported macros 2026-02-25 08:38:54 +01:00
Fabien Potencier e5eb95d0d7 Add getOperatorTokens() to ExpressionParserInterface to separate operator token registration from parser identity 2026-02-24 21:13:06 +01:00
brandonkelly a9ac993938 Ensure filters/attributes aren't mistaken for operators 2026-02-24 21:10:18 +01:00
Fabien Potencier 54d5c004b4 Deprecate passing a non-AbstractExpression node to Parser::setParent() 2026-02-22 15:28:59 +01:00
Fabien Potencier 751a187f07 feature #4748 Support short-circuiting in null-safe operator chains (HypeMC)
This PR was merged into the 3.x branch.

Discussion
----------

Support short-circuiting in null-safe operator chains

This PR adds short-circuiting for null-safe operator chains, using the same rules as PHP, `PropertyAccess`, and the `ExpressionLanguage`.

Previously, only the immediate null-safe access was guarded. With this change, as soon as a `null` is encountered at a null-safe access, the rest of the chain is skipped.

My approach was to move the null check outside of the `getAttribute()` calls so the expression can immediately return `null`, eg:

```twig
foo?.bar.baz
```

Before:

```php
yield $this->env
    ->getRuntime('Twig\Runtime\EscaperRuntime')
    ->escape(
        CoreExtension::getAttribute(
            $this->env,
            $this->source,
            (
                null === (
                    $_v0 = (
                        isset($context['foo']) || array_key_exists('foo', $context)
                            ? $context['foo']
                            : throw new RuntimeError('Variable "foo" does not exist.', 3, $this->source)
                    )
                )
                    ? null
                    : CoreExtension::getAttribute(
                        $this->env,
                        $this->source,
                        $_v0,
                        'bar',
                        [],
                        'any',
                        false,
                        false,
                        false,
                        3
                    )
            ),
            'baz',
            [],
            'any',
            false,
            false,
            false,
            3
        ),
        'html',
        null,
        true
    );
```

Now:

```php
yield $this->env
    ->getRuntime('Twig\Runtime\EscaperRuntime')
    ->escape(
        (
            null === (
                $_v0 = (
                    isset($context['foo']) || array_key_exists('foo', $context)
                        ? $context['foo']
                        : throw new RuntimeError('Variable "foo" does not exist.', 3, $this->source)
                )
            )
                ? null
                : CoreExtension::getAttribute(
                    $this->env,
                    $this->source,
                    CoreExtension::getAttribute(
                        $this->env,
                        $this->source,
                        $_v0,
                        'bar',
                        [],
                        'any',
                        false,
                        false,
                        false,
                        3
                    ),
                    'baz',
                    [],
                    'any',
                    false,
                    false,
                    false,
                    3
                )
        ),
        'html',
        null,
        true
    );
```

Commits
-------

d56e8e2dba Support short-circuiting in null-safe operator chains
2026-02-08 19:02:03 +01:00
Matthias Pigulla 04aa3df49f Add html_attr_relaxed escaping strategy 2026-02-08 18:59:07 +01:00
Fabien Potencier df893829f2 feature #4759 Add support for renaming variables in object destructuring (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Add support for renaming variables in object destructuring

Closes #4747

Commits
-------

3cc1b5233c Add support for renaming variables in object destructuring
2026-02-07 14:22:40 +01:00
Fabien Potencier 861215c507 Fix CS 2026-02-07 09:07:38 +01:00
HypeMC d56e8e2dba Support short-circuiting in null-safe operator chains 2026-02-06 22:36:57 +01:00
Fabien Potencier 3cc1b5233c Add support for renaming variables in object destructuring 2026-02-06 22:12:59 +01:00
HypeMC a16ac6bd35 Fix null-safe operator test 2026-01-25 04:57:19 +01:00
Fabien Potencier 8a0f8acbdf Add support for object and mapping destructuring 2026-01-21 13:21:14 +01:00
Fabien Potencier bb99af3b39 Assignment operator array destructuring 2026-01-21 08:46:28 +01:00