---
id: "CVE-2026-46633"
kind: "vulnerability"
aliases: ["CVE-2026-46633", "GHSA-7p85-w9px-jpjp"]
title: "Twig: PHP code injection via `{% use %}` template name"
severity: "critical"
cvss: 9.8
epss: 0.00688
exploited: false
status: "open"
category: "package"
products: [{"name": "twig/twig", "fixed": ["3.26.0"], "affected": ">= 1.15.1, < 3.26.0", "ecosystem": "composer"}, {"name": "symfony twig", "fixed": ["3.26.0"], "affected": "< 3.26.0", "ecosystem": "vendor"}]
ecosystems: ["composer", "vendor"]
tags: ["composer", "cwe-94", "laravel", "package", "php", "symfony", "twig"]
not_affected_if: ["no-untrusted-template-names", "twig-3.26.0-or-later", "twig-below-1.15.1"]
published_at: "2026-05-21T21:24:53+00:00"
first_seen_at: "2026-11-04T00:01:24+00:00"
updated_at: "2026-11-04T00:16:19+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-7p85-w9px-jpjp", "first_seen_at": "2026-11-04T00:01:24+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-46633", "first_seen_at": "2026-11-04T00:16:19+00:00"}]
---

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

Twig's compiler fails to escape single quotes in template names used by the {% use %} tag, so a crafted name breaks out of a generated PHP string. The injected PHP runs when the compiled cache file is first loaded, which lets an attacker run code on the server even inside Twig's sandbox.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- composer:twig/twig affected >= 1.15.1, < 3.26.0 fixed 3.26.0
- vendor:symfony twig affected < 3.26.0 fixed 3.26.0

## How to check

- Check the installed version with `composer show twig/twig` and look at the version line.
- Look in composer.lock for `twig/twig` and note the version.
- Treat any version from `1.15.1` up to, but not including, `3.26.0` as exposed.

## Fix

- Upgrade `twig/twig` to `3.26.0`.

## Timeline

- 2026-11-04T00:01:24+00:00 ghsa https://github.com/advisories/GHSA-7p85-w9px-jpjp
- 2026-11-04T00:16:19+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-46633

## Documents

- [advisory] Maintainer's advisory: api.github.com https://api.github.com/repos/twigphp/Twig/security-advisories/GHSA-7p85-w9px-jpjp
- [advisory] Maintainer's advisory: github.com https://github.com/twigphp/Twig/security/advisories/GHSA-7p85-w9px-jpjp
- [fix] Patch: github.com https://github.com/twigphp/Twig/commit/679447fa29083043665482ccf7d64372472621b8
- [fix] Patch: github.com https://github.com/twigphp/Twig/commit/a2c6db7ea7d2c90923e6708019ec1442526d1c30
- [fix] Patch: github.com https://github.com/twigphp/Twig/commit/e9ff55f6910832428e48a35b2e0748189ad49ae3
- [fix] Release: github.com https://github.com/twigphp/Twig/releases/tag/v3.26.0

## From the sources

### 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.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
