Skip to content

Update dependency twig/twig to v3 [SECURITY] - #26

Open
renovate[bot] wants to merge 1 commit into
masterfrom
renovate/packagist-twig-twig-vulnerability
Open

renovate[bot] wants to merge 1 commit into
masterfrom
renovate/packagist-twig-twig-vulnerability

Conversation

@renovate

@renovate renovate Bot commented Nov 7, 2024

Copy link
Copy Markdown
Contributor

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
twig/twig (source) ^1.0||^2.03.27.0 age confidence

Twig Sandbox Information Disclosure

CVE-2019-9942 / GHSA-vxrc-68xx-x48g

More information

Details

A sandbox information disclosure exists in Twig before 1.38.0 and 2.x before 2.7.0 because, under some circumstances, it is possible to call the __toString() method on an object even if not allowed by the security policy in place.

Severity

  • CVSS Score: 3.7 / 10 (Low)
  • Vector String: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig may load a template outside a configured directory when using the filesystem loader

CVE-2022-39261 / GHSA-52m2-vc4m-jj33

More information

Details

Description

When using the filesystem loader to load templates for which the name is a user input, it is possible to use the source or include statement to read arbitrary files from outside the templates directory when using a namespace like @somewhere/../some.file (in such a case, validation is bypassed).

Resolution

We fixed validation for such template names.

Even if the 1.x branch is not maintained anymore, a new version has been released.

Credits

We would like to thank Dariusz Tytko for reporting the issue and Fabien Potencier for fixing the issue.

Severity

  • CVSS Score: 7.5 / 10 (High)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig has a possible sandbox bypass

CVE-2024-45411 / GHSA-6j75-5wfj-gh66

More information

Details

Description

Under some circumstances, the sandbox security checks are not run which allows user-contributed templates to bypass the sandbox restrictions.

The security issue happens when all these conditions are met:

  • The sandbox is disabled globally;
  • The sandbox is enabled via a sandboxed include() function which references a template name (like included.twig) and not a Template or TemplateWrapper instance;
  • The included template has been loaded before the include() call but in a non-sandbox context (possible as the sandbox has been globally disabled).
Resolution

The patch ensures that the sandbox security checks are always run at runtime.

Credits

We would like to thank Fabien Potencier for reporting and fixing the issue.

Severity

  • CVSS Score: 5.8 / 10 (Medium)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:H

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig has unguarded calls to __toString() when nesting an object into an array

CVE-2024-51754 / GHSA-6377-hfv9-hqf6

More information

Details

Description

In a sandbox, an attacker can call __toString() on an object even if the __toString() method is not allowed by the security policy when the object is part of an array or an argument list (arguments to a function or a filter for instance).

Resolution

The sandbox mode now checks the __toString() method call on all objects.

The patch for this issue is available here for the 3.11.x branch, and here for the 3.x branch.

Credits

We would like to thank Jamie Schouten for reporting the issue and Fabien Potencier for providing the fix.

Severity

  • CVSS Score: 2.1 / 10 (Low)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig has unguarded calls to __isset() and to array-accesses when the sandbox is enabled

CVE-2024-51755 / GHSA-jjxq-ff2g-95vh

More information

Details

Description

In a sandbox, and attacker can access attributes of Array-like objects as they were not checked by the security policy.
They are now checked via the property policy and the __isset() method is now called after the security check.
This is a BC break.

Resolution

The sandbox mode now ensures access to array-like's properties is allowed.

The patch for this issue is available here for the 3.11.x branch, and here for the 3.x branch.

Credits

We would like to thank Jamie Schouten for reporting the issue and Nicolas Grekas for providing the fix.

Severity

  • CVSS Score: 2.1 / 10 (Low)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig: The spaceless filter implicitly marks its output as safe

CVE-2026-46628 / GHSA-4j38-f5cw-54h7

More information

Details

Description

The spaceless filter is registered with is_safe => ['html'], which means Twig's autoescaper does not escape its output in an HTML context. As a result, applying spaceless to attacker-controlled input that contains markup emits the markup unescaped even when the developer never wrote |raw and autoescape is enabled.

Example:

{% set payload = '<script>alert()</script>' %}
{{ payload }}          {# escaped #}
{{ payload|spaceless }} {# not escaped #}

The filter is deprecated but still functional. With the deprecation, some downstream projects (e.g. Drupal modules) have duplicated the filter and inherited the same is_safe flag.

Resolution

The spaceless filter no longer marks its output as safe. Documentation has been updated to warn that spaceless should not be applied to unsanitised user input.

Credits

Twig would like to thank Pierre Rudloff for reporting the issue.

Severity

  • CVSS Score: 1.3 / 10 (Low)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:U

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig: PHP code injection via {% use %} template name

CVE-2026-46633 / GHSA-7p85-w9px-jpjp

More information

Details

Description

Compiler::string() escapes ", $, \, NUL and TAB when generating PHP double-quoted string literals, but does not escape single quotes. In ModuleNode::compileConstructor(), the template name from a {% use %} tag is compiled via subcompile() -> string() and placed inside a surrounding PHP single-quoted string literal. A template name containing a single quote terminates that surrounding string early, allowing arbitrary PHP expressions to be injected into the compiled cache file.

The injected code executes within the PHP process when the cache file is first loaded, bypassing the Twig sandbox entirely and achieving remote code execution. SecurityPolicy unconditionally allows {% use %} regardless of the configured allowedTags, so this primitive is reachable from sandboxed templates as well.

Resolution

Compiler::string() now also escapes single quotes so that template names placed inside single-quoted PHP literals can no longer break out of the surrounding context.

Credits

Twig would like to thank Anvil Secure in collaboration with Claude and Anthropic Research for reporting the issue and providing the fix.

Severity

  • CVSS Score: 9.3 / 10 (Critical)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig: Sandbox property allowlist bypass via the column filter (array_column on objects)

CVE-2026-46635 / GHSA-vcc8-phrv-43wj

More information

Details

Description

The column filter passes its input straight to PHP's native array_column(). When the array elements are objects, array_column() reads $obj->$name (and $obj->$index) directly, including invoking __get/__isset. Because this property read happens entirely in PHP native code and never reaches CoreExtension::getAttribute(), SandboxExtension::checkPropertyAllowed() is never consulted.

An untrusted template author with column in their allowedFilters list can therefore read any public or magic property of any object reachable in the render context, regardless of the SecurityPolicy allowedProperties list. This is a variant of CVE-2024-51755 / GHSA-jjxq-ff2g-95vh that the ArrayAccess-focused fix did not cover.

Resolution

The column filter now routes object property reads through the sandbox-aware attribute accessor so the property allowlist is enforced.

Credits

Twig: would like to thank Claude Mythos Preview (via Project Glasswing) for reporting the issue and providing the fix.

Severity

  • CVSS Score: 2.1 / 10 (Low)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig: {% sandbox %}{% include %} skips checkSecurity() on cached templates (incomplete fix for CVE-2024-45411)

CVE-2026-46638 / GHSA-7fxw-r6jv-74c8

More information

Details

Description

The fix for CVE-2024-45411 / GHSA-6j75-5wfj-gh66 added an explicit $loaded->unwrap()->checkSecurity() call in CoreExtension::include() so that a template already cached in Environment::$loadedTemplates is re-checked when included with sandboxed = true.

The deprecated but still functional {% sandbox %}{% include ... %}{% endsandbox %} tag path was not updated: it compiles to enableSandbox(); yield from $this->load(...)->unwrap()->yield(...); disableSandbox(); with no checkSecurity() re-invocation. If the included template was loaded once outside the sandbox in the same Environment instance, its constructor (and therefore its compiled checkSecurity() call) already ran while isSandboxed() was false, so the tags/filters/functions allowlist enforced by SecurityPolicy::checkSecurity() is never applied.

An attacker who can author the included template gains access to every filter, function and tag registered in the environment, regardless of the sandbox policy.

Resolution

The compiled output of {% sandbox %}{% include %} now calls checkSecurity() on the loaded template, matching the behaviour of CoreExtension::include() with sandboxed = true.

Credits

Twig would like to thank Claude Mythos Preview (via Project Glasswing) for reporting the issue and providing the fix.

Severity

  • CVSS Score: 5.8 / 10 (Medium)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:H

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig: Sandbox: multiple __toString() policy bypasses via unguarded string coercion points

CVE-2026-47732 / GHSA-pr2w-4gpj-cpq4

More information

Details

Description

SandboxNodeVisitor enforces SecurityPolicy::checkMethodAllowed() for implicit __toString() calls by wrapping selected AST nodes in CheckToStringNode. The set of wrapped nodes is incomplete, and several Twig language constructs still trigger PHP string coercion on a Stringable operand without first consulting the policy. A sandboxed template author can therefore invoke __toString() on any object reachable in the render context, even when __toString on its class is not allowlisted.

Confirmed bypass vectors:

  • Conditional expressions (a ? b : c, a ?: b, a ?? b) used as the input of a string-coercing filter or as a filter/function argument.
  • The matches operator and the loose comparison operators (==, !=, <, >, <=, >=, <=>), which coerce a Stringable operand to string and can be used as an oracle to recover the value byte by byte (no tag, filter or function needs to be allowlisted).
  • Twig tests in general (which were never policy-gated), in particular is empty which casts a Stringable value via (string) $value in CoreExtension::testEmpty().
  • Null-coalesce expressions nested in concatenation, and the direct output of allowed functions or filters that return a Stringable object.
  • Arguments passed to allowed object methods, template-name expressions of template-loading tags (include, extends, use, ...), dynamic attribute/property names, and spread arguments from Traversable objects.
  • The do tag and the .. range operator.
Resolution

The sandbox now wraps every child node that the parent will string-coerce at runtime, instead of relying on a hardcoded list of node types in SandboxNodeVisitor. A new Twig\Node\CoercesChildrenToStringInterface lets nodes declare which of their children must be guarded; core nodes (concatenation, comparison and range binaries, filter/function/test expressions, do, include, extends, use, ...) implement it. Spread arguments are materialised and policy-checked via the new SandboxExtension::ensureSpreadAllowed(), and dynamic attribute names are checked at runtime inside CoreExtension::getAttribute().

Credits

Twig would like to thank Anthropic Glasswing and El Kharoubi Iosif for reporting the issues, and Fabien Potencier for providing the fixes.

Severity

High

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig: Sandbox __toString() policy bypass via dynamic mapping keys

CVE-2026-48806 / GHSA-5v5v-ww74-355v

More information

Details

Description

This is a residual bypass of CVE-2026-47732 / GHSA-pr2w-4gpj-cpq4 left after the initial fix for unguarded __toString() calls.

In 3.26.0 the sandbox visitor was extended to wrap every child node that its parent will string-coerce at runtime with CheckToStringNode, gated by the new CoercesChildrenToStringInterface. ArrayExpression did not implement the interface for its mapping keys: when a dynamic key expression resolves to a Stringable object, ArrayExpression::compile() emits a raw (string) cast (via StringCastUnary for ContextVariable keys, and no cast at all for richer key expressions). PHP then invokes __toString() directly, without ever calling SandboxExtension::ensureToStringAllowed().

A sandboxed template author can therefore trigger __toString() on any object reachable in the render context by using it as a dynamic mapping key, for example:

{% set arr = {(obj): "value"} %}

Direct output of the same object is correctly blocked, which makes this a clear policy enforcement gap. The reliable demonstrated impact is unauthorised disclosure of data returned by __toString().

Resolution

ArrayExpression now declares its dynamic mapping keys as string-coercion sites through CoercesChildrenToStringInterface, so the sandbox visitor wraps them with CheckToStringNode and the policy is consulted before PHP coerces the key to a string. The compiler also keeps an explicit (string) cast around the wrapped expression so PHP type errors on non-string keys are preserved.

As a side effect, any expression is now accepted as a dynamic mapping key (not only context variables); this is documented as a new feature on the 3.x branch.

Credits

Twig would like to thank El Kharoubi Iosif for reporting the issue and Fabien Potencier for providing the fix.

Severity

Medium

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig: Sandbox __toString() policy bypass via Traversable in join and replace filters

CVE-2026-48807 / GHSA-8x9c-rmqh-456c

More information

Details

Description

This is a residual bypass of CVE-2026-47732 / GHSA-pr2w-4gpj-cpq4 left after the initial fix for unguarded __toString() calls. It covers two related coercion points that were not caught by the original patch.

Traversable in join and replace filters. SandboxExtension::ensureToStringAllowed() recurses into PHP arrays so that a Stringable object hidden inside an array argument cannot be string-coerced without consulting the security policy. The recursion stops at PHP arrays: a Traversable value passed at the same position is not materialised, so its contents are not policy-checked. CoreExtension::join() and CoreExtension::replace() later materialise such Traversable inputs through self::toArray() and feed them to implode() / strtr(), both of which implicitly call __toString() on contained Stringable objects. The bypass also reproduces when the container implements both Stringable and Traversable: the container's own __toString() is policy-checked, but the elements yielded by getIterator() are not, and the consuming filters still coerce them to string.

in and not in operators. InBinary and NotInBinary compile to CoreExtension::inFilter(), which falls through to PHP's <=> operator when comparing a string with a Stringable object. PHP coerces the object to string via __toString() without the sandbox policy being consulted. Beyond the direct side effect, in can also be used as a content-leak oracle: each probe against an attacker-chosen needle leaks one bit of equality, and chained probes can reconstruct the string returned by __toString() even when every method is denied. The bypass reproduces with both array and Traversable haystacks, and on both operand sides.

A sandboxed template author who is allowed to call join / replace, or to use the in / not in operators, can therefore trigger a disallowed __toString() method on objects reachable from the render context, even when that method is not on SecurityPolicy::$allowedMethods. The bypass reproduces both under global sandbox mode and when sandboxing is enabled through SourcePolicyInterface.

Resolution

SandboxExtension::ensureToStringAllowed() now also recurses into Traversable operands when sandboxing is active for the current source: each value is materialised once and run through the same array-recursion path, so the policy is consulted before the filter implementation can coerce contained objects to strings. This applies to plain Traversable operands as well as to containers that implement both Stringable and Traversable: the container's own __toString() is still policy-checked, and the yielded elements are additionally checked. The materialisation is guarded by isSandboxed($source) so that non-sandboxed code paths do not pay the cost or change generator-exhaustion semantics.

InBinary and NotInBinary now implement Twig\Node\CoercesChildrenToStringInterface and declare both operands as string-coerced, so SandboxNodeVisitor wraps each operand in CheckToStringNode. The policy is consulted before CoreExtension::inFilter() reaches PHP's <=> operator, matching the existing protection on the other comparison binaries (Equal, Less, Greater, Spaceship, ...).

Credits

Twig would like to thank Vincent55 Yang and Fabien Potencier for reporting the issues and Fabien Potencier for providing the fix.

Severity

Medium

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig: Sandbox property allowlist bypass via the column filter under SourcePolicyInterface

CVE-2026-48808 / GHSA-h8vq-8gpg-mhcg

More information

Details

Description

This is a residual bypass of CVE-2026-46635 / GHSA-vcc8-phrv-43wj that only affects sandboxing enabled through SourcePolicyInterface (and not the regular global sandbox mode).

CoreExtension::column() receives the active sandbox state via the needs_is_sandboxed channel as a boolean $isSandboxed, but then routes the per-element property reads through SandboxExtension::checkPropertyAllowed() without forwarding the current Source. SandboxExtension::checkPropertyAllowed() re-evaluates isSandboxed($source) internally; with $source = null the SourcePolicyInterface-driven decision is lost, the method short-circuits to "not sandboxed", and the property allowlist is never consulted.

A template author whose sandbox is gated by a SourcePolicyInterface and who has column on their allowedFilters list can therefore read any public or magic property of any object reachable in the render context, regardless of SecurityPolicy::$allowedProperties. Direct attribute access to the same property is blocked, and the same payload is also blocked under global sandbox mode, which makes this a clear policy enforcement gap rather than a configuration issue.

Resolution

CoreExtension::column() no longer goes through the SandboxExtension wrapper for the property check. It calls the security policy directly: the per-source decision is already captured by the $isSandboxed boolean computed at the call site, so the property allowlist is enforced consistently for both global and source-policy sandboxing.

Credits

Twig would like to thank Vincent55 Yang for reporting the issue and Fabien Potencier for providing the fix.

Severity

Medium

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig: Sandbox state regression in deprecated internal wrappers in src/Resources/core.php

CVE-2026-48805 / GHSA-p42q-9prx-q5wq

More information

Details

Description

The 3.26.0 source-policy hardening changed the signature of CoreExtension::checkArrow() to take a boolean $isSandboxed instead of an Environment, and added the same $isSandboxed argument to CoreExtension::arraySome() and CoreExtension::arrayEvery(). Compiled templates were updated to pass the per-source sandbox state computed at the call site.

The deprecated internal wrappers exposed in src/Resources/core.php for legacy third-party code (twig_check_arrow_in_sandbox(), twig_array_some(), twig_array_every()) were not updated:

  • twig_array_some() and twig_array_every() call CoreExtension::arraySome() / arrayEvery() without forwarding the sandbox state. The underlying methods default $isSandboxed to false, so the callable-must-be-a-Closure restriction is silently bypassed in sandbox mode and a string callable such as 'strcmp' is accepted.
  • twig_check_arrow_in_sandbox() passes the Environment object where CoreExtension::checkArrow() now expects a bool, which throws a TypeError on PHP 8+.

Compiled Twig templates are not affected: they call CoreExtension::* directly with the correct arguments. Applications are only impacted if they still call the deprecated twig_* helpers on top of a sandboxed Environment.

Resolution

The three wrappers now resolve the current sandbox state via twig_resolve_is_sandboxed() (the same helper compiled templates use), and forward it to the corresponding CoreExtension::* method. twig_check_arrow_in_sandbox() no longer triggers a TypeError, and twig_array_some() / twig_array_every() now enforce the same sandbox restriction as compiled templates.

Credits

We would like to thank El Kharoubi Iosif for reporting the issue and Fabien Potencier for providing the fix.

Severity

Low

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Twig: Sandbox filter, tag and function allow-list bypass when sandbox state changes between renders for a cached Template

CVE-2026-49981 / GHSA-529h-vh3j-85hq

More information

Details

Description

The per-template filter, tag and function allow-list check is compiled into the checkSecurity() method of each Template subclass and was invoked once from the constructor, gated by SandboxExtension::isSandboxed($source). Template instances are then cached on the Environment in $loadedTemplates, so the verdict computed at construction time was sticky for the rest of the process.

Any later change of sandbox state on the same Environment left that cached verdict in place: toggling SandboxExtension::enableSandbox()/disableSandbox(), swapping the policy via setSecurityPolicy(), a SourcePolicyInterface decision flip, or simply having a parent, macro or included template pre-instantiated outside the sandbox before a sandboxed render reached it. In all of these cases, the filters, tags and functions used by the affected template kept running with the original (typically empty) check, bypassing the SecurityPolicy allow-list.

Method, property and __toString allow-lists are not affected: they are enforced at every call site at runtime through SandboxExtension::checkMethodAllowed(), checkPropertyAllowed() and ensureToStringAllowed(), which re-read the current state on every call.

Long-lived workers (FrankenPHP, RoadRunner, Symfony Messenger consumers, FPM with hot autoloading) that share a single Environment between sandboxed and non-sandboxed renders are the most exposed: a single non-sandboxed render of a shared layout pre-warms its Template instance, after which any later sandboxed render that extends, uses, includes or imports from that layout silently skips the filter/tag/function allow-list for the pre-warmed instance.

Resolution

The allow-list check is no longer run from the constructor. Template gains a public ensureSecurityChecked() method that calls the compiled checkSecurity() only when SandboxExtension::isSandboxed($source) returns true for the current source, and it is invoked at every entry point that can reach a Template instance whose security has not yet been verified against the current state: Template::yield(), Template::yieldBlock() (on the resolved block template, which covers extends, use, traits and parent blocks), Template::getParent() (which evaluates user code when the parent name is dynamic) and Template::getTemplateForMacro() (on the resolved macro template).

The explicit checkSecurity() calls previously emitted by IncludeNode and CoreExtension::include() are removed: the included template's own yield() now re-runs the check against the current sandbox state. The compiled checkSecurity() body is a cheap walk over compile-time-static arrays, so the per-render cost is negligible. Old cached compiled PHP files keep working unchanged: the constructor-time call they still contain is idempotent.

Credits

Twig would like to thank Fabien Potencier for reporting and fixing the issue.

Severity

  • CVSS Score: 8.7 / 10 (High)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

twigphp/Twig (twig/twig)

v3.27.0

Compare Source

  • Add a strict mode to Twig\Sandbox\SecurityPolicy to opt-in to the 4.0 behavior for the extends/use tags and the parent/block/attribute functions, which are otherwise still implicitly allowed in a sandbox
  • Deprecate the fact that the parent, block, and attribute functions are always allowed in a sandboxed template
  • Fix sandbox filter/tag/function allow-list bypass when the sandbox state changed between renders of a cached Template instance
  • Fix PHP 8.1+ implicit float-to-int deprecation triggered by sandboxed ArrayAccess attribute access with a float key
  • Restrict allowed classes in Twig\Profiler\Profile::unserialize() to prevent arbitrary class instantiation
  • Escape root profile name in HtmlDumper
  • Fix sandbox bypass in deprecated internal wrappers twig_array_some(), twig_array_every(), and twig_check_arrow_in_sandbox() (src/Resources/core.php)
  • Deprecate the Twig\Sandbox\SourcePolicyInterface interface with no replacement
  • Fix sandbox bypass in the "column" filter when sandboxing is enabled via SourcePolicyInterface
  • Fix sandbox __toString bypass via Traversable arguments to the join and replace filters (also covers containers that implement both Stringable and Traversable)
  • Fix sandbox __toString bypass via the in and not in operators
  • Prevent a stack overflow in SandboxExtension::ensureToStringAllowed() when a self-referencing iterable is passed to a sandboxed template
  • Add support for any expression as a dynamic mapping key (attribute access, filters, ...)
  • Fix sandbox __toString policy bypass via dynamic mapping keys

v3.26.0

Compare Source

  • Document that the sandbox doesn't protect against resource exhaustion
  • Document template_from_string caveats when used in a sandboxed environment
  • Add docs on Markup about the goal of this class in the context of a sandbox
  • Pre-escape HTML input on the spaceless filter
  • Pre-escape HTML input on inline_css and inky_to_html filters
  • Fix XSS by adjusting is_safe annotation on HTML-emitting filters
  • [Profiler] Escape template and profile names in HtmlDumper
  • Fix unbounded memoisation of IntlDateFormatter / NumberFormatter
  • Fix sandbox bypass in the "column" filter
  • Fix sandbox bypass in the {% sandbox %} tag when including a preloaded template
  • Fix sandbox bypass: PHP code injection via {% use %} template name
  • Fix sandbox bypass: PHP code injection via _self / import macro reference
  • Fix sandbox bypass in object destructuring assignment
  • Fix sandbox bypass: propagate Source to checkArrow for source-policy sandboxing
  • Encode single quotes as \x27 in Compiler::string() as a defense-in-depth measure
  • Fix sandbox __toString bypasses
  • Add Twig\Node\CoercesChildrenToStringInterface to let nodes declare which of their child nodes will be string-coerced at runtime so the sandbox wraps them with a __toString check

v3.25.0

Compare Source

  • Add a needs_is_sandboxed option for filters, functions, and tests
  • Use deterministic suffixes for generated embed classes
  • Lazy-load EscaperRuntime in EscaperExtension

v3.24.0

Compare Source

  • Deprecate not implementing the getOperatorTokens() method in ExpressionParserInterface implementations
  • Deprecate passing a non-AbstractExpression node to Twig\Node\Expression\Binary\MatchesBinary constructor
  • Deprecate passing a non-AbstractExpression node to Parser::setParent()
  • Add support for renaming variables in object destructuring ({name: userName} = user)
  • Add html_attr_relaxed escaping strategy that preserves :, @​, [, and ] for front-end framework attribute names
  • Add support for short-circuiting in null-safe operator chains
  • Add the html_attr function and html_attr_merge as well as html_attr_type filters

v3.23.0

Compare Source

  • Add = assignment operator (allows to set variables in expression or to replace the short-form of the set tag)
  • Add sequence, mapping, and object destructuring
  • Add ?. null-safe operator
  • Add === and !== operators (equivalent to the same as and not same as tests)
  • Fix opcache preload warning for unlinked anonymous class
  • Fix spread operator behavior

v3.22.2

Compare Source

  • Fix "cycle" with non-countable ArrayAccess + Traversable objects
  • Use "getShareDir" as an indicator of Symfony version in Symfony bundle
  • Fix escaper compatibility with PHP 8.5

v3.22.1

Compare Source

  • Add support for Symfony 8

v3.22.0

Compare Source

  • Add support for two words test in guard tag
  • Add Environment::registerUndefinedTestCallback()
  • Fix compatibility with Symfony 8
  • Fix accessing arrays with stringable objects as key
  • Avoid errors when failing to guess the template info for an error
  • Fix expression parser compatibility layer
  • Fix compiling 'index' with repr (not string) in EmbedNode
  • Update configuration keys + allow extra keys for CommonMark extensions
  • Allow usage of other Markdown converters than CommonMark in LeagueMarkdown

v3.21.1

Compare Source

  • Fix ExtensionSet usage of BinaryOperatorExpressionParser

v3.21.0

Compare Source

  • Fix wrong array index
  • Deprecate Template::loadTemplate()
  • Fix testing and expression when it evaluates to an instance of Markup
  • Add ReturnPrimitiveTypeInterface (and sub-interfaces for number, boolean, string, and array)
  • Add SupportDefinedTestInterface for expression nodes supporting the defined test
  • Deprecate using the | operator in an expression with + or - without using parentheses to clarify precedence
  • Deprecate operator precedence outside of the [0, 512] range
  • Introduce expression parser classes to describe operators and operands provided by extensions
    instead of arrays (it comes with many deprecations that are documented in
    the deprecated documentation chapter)
  • Deprecate the Twig\ExpressionParser, and Twig\OperatorPrecedenceChange classes
  • Add attributes AsTwigFilter, AsTwigFunction, and AsTwigTest to ease extension development

v3.20.0

Compare Source

  • Fix support for ignoring syntax errors in an undefined handler in guard
  • Add configuration for Commonmark
  • Fix wrong array index
  • Bump minimum PHP version to 8.1
  • Add support for registering callbacks for undefined functions, filters or token parsers in the IntegrationTestCase
  • Use correct line number for ForElseNode
  • Fix timezone conversion on strings

v3.19.0

Compare Source

  • Fix a security issue where escaping was missing when using ??
  • Deprecate Token::getType(), use Token::test() instead
  • Add Token::toEnglish()
  • Add ForElseNode
  • Deprecate Twig\ExpressionParser::parseOnlyArguments() and
    Twig\ExpressionParser::parseArguments() (use
    Twig\ExpressionParser::parseNamedArguments() instead)
  • Fix constant() behavior when used with ??
  • Add the invoke filter
  • Make {} optional for the types tag
  • Add LastModifiedExtensionInterface and implementation in AbstractExtension to track modification of runtime classes
  • Ignore static properties when using the dot operator

v3.18.0

Compare Source

  • Support for invoking closures
  • Fix unary operator precedence change
  • Ignore SyntaxError exceptions from undefined handlers when using the guard tag
  • Add a way to stream template rendering (TemplateWrapper::stream() and TemplateWrapper::streamBlock())

v3.17.1

Compare Source

  • Fix the null coalescing operator when the test returns null
  • Fix the Elvis operator when used as '? :' instead of '?:'

v3.17.0

Compare Source

  • Fix ArrayAccess with objects as keys
  • Support underscores in number literals
  • Deprecate ConditionalExpression and NullCoalesceExpression (use ConditionalTernary and NullCoalesceBinary instead)

v3.16.0

Compare Source

  • Deprecate InlinePrint
  • Fix having macro variables starting with an underscore
  • Deprecate not passing a Source instance to TokenStream
  • Deprecate returning null from TwigFilter::getSafe() and TwigFunction::getSafe(), return [] instead

v3.15.0

Compare Source

  • [BC BREAK] Add support for accessing class constants with the dot operator;
    this can be a BC break if you don't use UPPERCASE constant names
  • Add Spanish inflector support for the plural and singular filters in the String extension
  • Deprecate TempNameExpression in favor of LocalVariable
  • Deprecate NameExpression in favor of ContextVariable
  • Deprecate AssignNameExpression in favor of AssignContextVariable
  • Remove MacroAutoImportNodeVisitor
  • Deprecate MethodCallExpression in favor of MacroReferenceExpression
  • Fix support for the "is defined" test on _self.xxx (auto-imported) macros
  • Fix support for the

Important

✂ PR body was truncated to here.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate

renovate Bot commented Nov 7, 2024

Copy link
Copy Markdown
Contributor Author

⚠️ Artifact update problem

Renovate failed to update an artifact related to this branch. You probably do not want to merge this PR as-is.

♻ Renovate will retry this branch, including artifacts, only when one of the following happens:

  • any of the package files in this branch needs updating, or
  • the branch becomes conflicted, or
  • you click the rebase/retry checkbox if found above, or
  • you rename this PR's title to start with "rebase!" to trigger it manually

The artifact failure details are included below:

File name: composer.lock
Command failed: composer update twig/twig:3.27.0 --with-dependencies --ignore-platform-reqs --no-ansi --no-interaction --no-scripts --no-autoloader --no-plugins
Deprecation Notice: Composer\Command\ShowCommand::printPackageInfo(): Implicitly marking parameter $latestPackage as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/src/Composer/Command/ShowCommand.php:586
Deprecation Notice: Composer\Command\ShowCommand::printMeta(): Implicitly marking parameter $latestPackage as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/src/Composer/Command/ShowCommand.php:614
Deprecation Notice: Composer\Command\ShowCommand::printPackageInfoAsJson(): Implicitly marking parameter $latestPackage as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/src/Composer/Command/ShowCommand.php:762
Deprecation Notice: Composer\Command\ArchiveCommand::archive(): Implicitly marking parameter $composer as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/src/Composer/Command/ArchiveCommand.php:108
Deprecation Notice: Constant E_STRICT is deprecated since 8.4, the error level was removed in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/src/Composer/Util/Silencer.php:36
Deprecation Notice: Composer\Json\JsonFile::__construct(): Implicitly marking parameter $rfs as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/src/Composer/Json/JsonFile.php:51
Deprecation Notice: Composer\Json\JsonFile::__construct(): Implicitly marking parameter $io as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/src/Composer/Json/JsonFile.php:51
Deprecation Notice: JsonSchema\Constraints\BaseConstraint::__construct(): Implicitly marking parameter $factory as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php:41
Deprecation Notice: JsonSchema\Constraints\BaseConstraint::addError(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php:46
Deprecation Notice: JsonSchema\Constraints\BaseConstraint::addError(): Implicitly marking parameter $more as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php:46
Deprecation Notice: JsonSchema\Constraints\Factory::__construct(): Implicitly marking parameter $schemaStorage as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php:77
Deprecation Notice: JsonSchema\Constraints\Factory::__construct(): Implicitly marking parameter $uriRetriever as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php:78
Deprecation Notice: JsonSchema\Constraints\Constraint::incrementPath(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php:42
Deprecation Notice: JsonSchema\Constraints\Constraint::checkArray(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php:68
Deprecation Notice: JsonSchema\Constraints\Constraint::checkObject(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php:86
Deprecation Notice: JsonSchema\Constraints\Constraint::checkType(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php:103
Deprecation Notice: JsonSchema\Constraints\Constraint::checkUndefined(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php:119
Deprecation Notice: JsonSchema\Constraints\Constraint::checkString(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php:136
Deprecation Notice: JsonSchema\Constraints\Constraint::checkNumber(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php:152
Deprecation Notice: JsonSchema\Constraints\Constraint::checkEnum(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php:168
Deprecation Notice: JsonSchema\Constraints\Constraint::checkFormat(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php:184
Deprecation Notice: JsonSchema\Constraints\ConstraintInterface::addError(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php:43
Deprecation Notice: JsonSchema\Constraints\ConstraintInterface::addError(): Implicitly marking parameter $more as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php:43
Deprecation Notice: JsonSchema\Constraints\ConstraintInterface::check(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php:64
Deprecation Notice: JsonSchema\SchemaStorage::__construct(): Implicitly marking parameter $uriRetriever as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php:20
Deprecation Notice: JsonSchema\SchemaStorage::__construct(): Implicitly marking parameter $uriResolver as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php:21
Deprecation Notice: JsonSchema\Constraints\SchemaConstraint::check(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php:31
Deprecation Notice: JsonSchema\Constraints\UndefinedConstraint::check(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php:34
Deprecation Notice: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php:55
Deprecation Notice: JsonSchema\Constraints\TypeConstraint::check(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php:42
Deprecation Notice: JsonSchema\Constraints\ObjectConstraint::check(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php:30
Deprecation Notice: JsonSchema\Constraints\ObjectConstraint::validatePatternProperties(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php:54
Deprecation Notice: JsonSchema\Constraints\ObjectConstraint::validateElement(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php:93
Deprecation Notice: JsonSchema\Constraints\ObjectConstraint::validateProperties(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php:135
Deprecation Notice: JsonSchema\Constraints\ObjectConstraint::validateMinMaxConstraint(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php:177
Deprecation Notice: JsonSchema\Constraints\StringConstraint::check(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php:25
Deprecation Notice: JsonSchema\Constraints\FormatConstraint::check(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php:27
Deprecation Notice: JsonSchema\Constraints\EnumConstraint::check(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php:25
Deprecation Notice: JsonSchema\Constraints\CollectionConstraint::check(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php:25
Deprecation Notice: JsonSchema\Constraints\CollectionConstraint::validateItems(): Implicitly marking parameter $path as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php:64
Deprecation Notice: Composer\Config::prohibitUrlByConfig(): Implicitly marking parameter $io as nullable is deprecated, the explicit nullable type must be used instead in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/src/Composer/Config.php:450
Deprecation Notice: Constant E_STRICT is deprecated since 8.4, the error level was removed in phar:///opt/containerbase/tools/composer/1.10.27/bin/composer/src/Composer/Util/Silencer.php:36

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
  [UnexpectedValueException]                                                                                                                                                                                                                                                                                                                                                                                                                                      
  Your github oauth token for github.com contains invalid characters: "**redacted**"  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  

update [--prefer-source] [--prefer-dist] [--dry-run] [--dev] [--no-dev] [--lock] [--no-custom-installers] [--no-autoloader] [--no-scripts] [--no-progress] [--no-suggest] [--with-dependencies] [--with-all-dependencies] [-v|vv|vvv|--verbose] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [-i|--interactive] [--root-reqs] [--] [<packages>]...


@renovate
renovate Bot force-pushed the renovate/packagist-twig-twig-vulnerability branch from 415e330 to 389407c Compare May 23, 2026 03:33
@renovate
renovate Bot force-pushed the renovate/packagist-twig-twig-vulnerability branch from 389407c to e1b4491 Compare July 2, 2026 04:06
@mergify

mergify Bot commented Jul 2, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

4 similar comments
@mergify

mergify Bot commented Jul 25, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@mergify

mergify Bot commented Jul 28, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@mergify

mergify Bot commented Aug 29, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@mergify

mergify Bot commented Sep 12, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants