GHSA-5v5v-ww74-355v

Suggest an improvement
Source
https://github.com/advisories/GHSA-5v5v-ww74-355v
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-5v5v-ww74-355v/GHSA-5v5v-ww74-355v.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-5v5v-ww74-355v
Aliases
Published
2026-06-30T18:42:49Z
Modified
2026-09-10T03:50:48Z
Summary
Twig: Sandbox `__toString()` policy bypass via dynamic mapping keys
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.

Database specific
{
    "cwe_ids": [
        "CWE-693",
        "CWE-863"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-30T18:42:49Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
}
References

Affected packages

Packagist / twig/twig

Package

Name
twig/twig
Purl
pkg:composer/twig/twig

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
3.27.0

Affected versions

1.*
1.3.0
1.4.0
1.5.0
1.5.1
1.6.0
1.6.1
1.6.2
1.6.3
1.6.4
1.6.5
v1.*
v1.7.0
v1.8.0
v1.8.1
v1.8.2
v1.8.3
v1.9.0
v1.9.1
v1.9.2
v1.10.0
v1.10.1
v1.10.2
v1.10.3
v1.11.0
v1.11.1
v1.12.0-RC1
v1.12.0
v1.12.1
v1.12.2
v1.12.3
v1.13.0
v1.13.1
v1.13.2
v1.14.0
v1.14.1
v1.14.2
v1.15.0
v1.15.1
v1.16.0
v1.16.1
v1.16.2
v1.16.3
v1.17.0
v1.18.0
v1.18.1
v1.18.2
v1.19.0
v1.20.0
v1.21.0
v1.21.1
v1.21.2
v1.22.0
v1.22.1
v1.22.2
v1.22.3
v1.23.0
v1.23.1
v1.23.2
v1.23.3
v1.24.0
v1.24.1
v1.24.2
v1.25.0
v1.26.0
v1.26.1
v1.27.0
v1.28.0
v1.28.1
v1.28.2
v1.29.0
v1.30.0
v1.31.0
v1.32.0
v1.33.0
v1.33.1
v1.33.2
v1.34.0
v1.34.1
v1.34.2
v1.34.3
v1.34.4
v1.35.0
v1.35.1
v1.35.2
v1.35.3
v1.35.4
v1.36.0
v1.37.0
v1.37.1
v1.38.0
v1.38.1
v1.38.2
v1.38.3
v1.38.4
v1.39.0
v1.39.1
v1.40.0
v1.40.1
v1.41.0
v1.42.0
v1.42.1
v1.42.2
v1.42.3
v1.42.4
v1.42.5
v1.43.0
v1.43.1
v1.44.0
v1.44.1
v1.44.2
v1.44.3
v1.44.4
v1.44.5
v1.44.6
v1.44.7
v1.44.8
v2.*
v2.0.0
v2.1.0
v2.2.0
v2.3.0
v2.3.1
v2.3.2
v2.4.0
v2.4.1
v2.4.2
v2.4.3
v2.4.4
v2.4.5
v2.4.6
v2.4.7
v2.4.8
v2.5.0
v2.6.0
v2.6.1
v2.6.2
v2.7.0
v2.7.1
v2.7.2
v2.7.3
v2.7.4
v2.8.0
v2.8.1
v2.9.0
v2.10.0
v2.11.0
v2.11.1
v2.11.2
v2.11.3
v2.12.0
v2.12.1
v2.12.2
v2.12.3
v2.12.4
v2.12.5
v2.13.0
v2.13.1
v2.14.0
v2.14.1
v2.14.2
v2.14.3
v2.14.4
v2.14.5
v2.14.6
v2.14.7
v2.14.8
v2.14.9
v2.14.10
v2.14.11
v2.14.12
v2.14.13
v2.15.0
v2.15.1
v2.15.2
v2.15.3
v2.15.4
v2.15.5
v2.15.6
v2.16.0
v2.16.1
v3.*
v3.0.0-BETA1
v3.0.0
v3.0.1
v3.0.2
v3.0.3
v3.0.4
v3.0.5
v3.1.0
v3.1.1
v3.2.1
v3.3.0
v3.3.1
v3.3.2
v3.3.3
v3.3.4
v3.3.5
v3.3.6
v3.3.7
v3.3.8
v3.3.9
v3.3.10
v3.4.0
v3.4.1
v3.4.2
v3.4.3
v3.5.0
v3.5.1
v3.6.0
v3.6.1
v3.7.0
v3.7.1
v3.8.0
v3.9.0
v3.9.1
v3.9.2
v3.9.3
v3.10.0
v3.10.1
v3.10.2
v3.10.3
v3.11.0
v3.11.1
v3.11.2
v3.11.3
v3.12.0
v3.13.0
v3.14.0
v3.14.1
v3.14.2
v3.15.0
v3.16.0
v3.17.0
v3.17.1
v3.18.0
v3.19.0
v3.20.0
v3.21.0
v3.21.1
v3.22.0
v3.22.1
v3.22.2
v3.23.0
v3.24.0
v3.25.0
v3.26.0

Database specific

last_known_affected_version_range
"<= 3.26.0"
source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-5v5v-ww74-355v/GHSA-5v5v-ww74-355v.json"