GHSA-2G2G-8P8H-FGWM
Vulnerability from github – Published: 2026-06-05 21:46 – Updated: 2026-06-05 21:47
VLAI
Summary
Twig: XSS in profiler HtmlDumper via unescaped template and profile names
Details
Description
Twig\Profiler\Dumper\HtmlDumper writes Profile::getTemplate() and Profile::getName() straight into its HTML output without escaping:
protected function formatTemplate(Profile $profile, $prefix): string
{
return \sprintf('%s└ <span style="background-color: %s">%s</span>', $prefix, self::$colors['template'], $profile->getTemplate());
}
The template name comes from the loader (the array key for ArrayLoader, a row id for a database-backed loader, etc.). When that name is attacker-controlled, the profiler dump emits arbitrary HTML, and any browser that renders it executes the injected markup. This is an output-encoding bug in profiler/debug tooling, not a sandbox escape.
Resolution
HtmlDumper now runs both Profile::getTemplate() and Profile::getName() through htmlspecialchars() before inserting them into the HTML output.
Credits
Twig would like to thank El Kharoubi Iosif for reporting the issue and Nicolas Grekas for fixing it.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "twig/twig"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.26.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-47730"
],
"database_specific": {
"cwe_ids": [
"CWE-79"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-05T21:46:26Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "### Description\n\n`Twig\\Profiler\\Dumper\\HtmlDumper` writes `Profile::getTemplate()` and `Profile::getName()` straight into its HTML output without escaping:\n\n```php\nprotected function formatTemplate(Profile $profile, $prefix): string\n{\n return \\sprintf(\u0027%s\u2514 \u003cspan style=\"background-color: %s\"\u003e%s\u003c/span\u003e\u0027, $prefix, self::$colors[\u0027template\u0027], $profile-\u003egetTemplate());\n}\n```\n\nThe template name comes from the loader (the array key for `ArrayLoader`, a row id for a database-backed loader, etc.). When that name is attacker-controlled, the profiler dump emits arbitrary HTML, and any browser that renders it executes the injected markup. This is an output-encoding bug in profiler/debug tooling, not a sandbox escape.\n\n### Resolution\n\n`HtmlDumper` now runs both `Profile::getTemplate()` and `Profile::getName()` through `htmlspecialchars()` before inserting them into the HTML output.\n\n### Credits\n\nTwig would like to thank El Kharoubi Iosif for reporting the issue and Nicolas Grekas for fixing it.",
"id": "GHSA-2g2g-8p8h-fgwm",
"modified": "2026-06-05T21:47:33Z",
"published": "2026-06-05T21:46:26Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/twigphp/Twig/security/advisories/GHSA-2g2g-8p8h-fgwm"
},
{
"type": "WEB",
"url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/twig/twig/CVE-2026-47730.yaml"
},
{
"type": "PACKAGE",
"url": "https://github.com/twigphp/Twig"
},
{
"type": "WEB",
"url": "https://github.com/twigphp/Twig/releases/tag/v3.26.0"
},
{
"type": "WEB",
"url": "https://symfony.com/cve-2026-47730"
}
],
"schema_version": "1.4.0",
"severity": [],
"summary": "Twig: XSS in profiler HtmlDumper via unescaped template and profile names"
}
Loading…
Loading…
Experimental. This forecast is provided for visualization only and may change without notice. Do not use it for operational decisions.
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Loading…
Loading…