Statamic's Antlers sanitizer cannot effectively sanitize malicious SVG
Description
Statamic is a flat-first, Laravel and Git powered content management system. Prior to version 4.10.0, the SVG tag does not sanitize malicious SVG. Therefore, an attacker can exploit this vulnerability to perform cross-site scripting attacks using SVG, even when using the sanitize function. Version 4.10.0 contains a patch for this issue.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Statamic CMS prior to 4.10.0 fails to sanitize SVG in the SVG tag, allowing stored XSS via manipulated SVG files.
Vulnerability
Overview
CVE-2023-36828 affects Statamic, a flat-first content management system built on Laravel and Git. In versions prior to 4.10.0, the SVG tag does not properly sanitize malicious SVG content, even when the sanitize function is explicitly used. The root cause is that the sanitize method in Svg.php (see [4]) did not apply any sanitization logic; it simply returned the SVG string unchanged. This allowed attackers to bypass the intended protection and inject arbitrary JavaScript or HTML within SVG elements [1][3].
Exploitation
Details
An attacker can exploit this vulnerability by uploading a crafted SVG file that contains malicious content, such as a ` with an embedded executing javascript: URLs, or other XSS vectors. The Statamic files controller only blocks certain file extensions (e.g., php, php3, php4, php5, phtml) but does not inspect SVG content. Therefore, a malicious SVG can be uploaded as a social media icon or other asset. When the SVG tag renders the file (even with the sanitize parameter set to true`), the payload is output without sanitization, leading to stored cross-site scripting (XSS) [3].
Impact
A successful exploit allows an attacker to execute arbitrary JavaScript in the context of a victim's browser. Since the SVG may be displayed in common layout areas like a footer, any user viewing a page containing the malicious SVG is affected. This can lead to session hijacking, credential theft, or other client-side attacks. The vulnerability is classified as stored XSS, requiring no authentication from the victim if the page is publicly accessible [3].
Mitigation
Statamic addressed this issue in version 4.10.0 by integrating the enshrined/svg-sanitize library into the SVG tag. The patch modifies the sanitize method to use the Sanitizer class, which allows administrators to configure allowed tags and attributes. The commit [2] shows the addition of the sanitization logic. Users should upgrade to Statamic 4.10.0 or later to remediate the vulnerability. No workarounds are documented for versions before 4.10.0.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
statamic/cmsPackagist | < 4.10.0 | 4.10.0 |
Affected products
2- statamic/cmsv5Range: < 4.10.0
Patches
1c714893ad92d[4.x] SVG tag sanitization (#8408)
3 files changed · +132 −2
composer.json+1 −0 modified@@ -12,6 +12,7 @@ "ext-json": "*", "ajthinking/archetype": "^1.0.3", "composer/composer": "^1.10.22 || ^2.2.12", + "enshrined/svg-sanitize": "^0.16.0", "facade/ignition-contracts": "^1.0", "guzzlehttp/guzzle": "^6.3 || ^7.0", "james-heinrich/getid3": "^1.9.21",
src/Tags/Svg.php+60 −1 modified@@ -2,6 +2,9 @@ namespace Statamic\Tags; +use enshrined\svgSanitize\data\AllowedAttributes; +use enshrined\svgSanitize\data\AllowedTags; +use enshrined\svgSanitize\Sanitizer; use Statamic\Facades\File; use Statamic\Facades\URL; use Statamic\Support\Str; @@ -47,11 +50,13 @@ public function index() $svg = $this->setTitleAndDesc($svg); } - return str_replace( + $svg = str_replace( '<svg', collect(['<svg', $attributes])->filter()->implode(' '), $svg ); + + return $this->sanitize($svg); } private function setTitleAndDesc($svg) @@ -79,4 +84,58 @@ private function setTitleAndDesc($svg) return $doc->saveHTML(); } + + private function sanitize($svg) + { + if ($this->params->bool('sanitize') === false) { + return $svg; + } + + $sanitizer = new Sanitizer; + $sanitizer->removeXMLTag(! Str::startsWith($svg, '<?xml')); + $sanitizer->setAllowedAttrs($this->getAllowedAttrs()); + $sanitizer->setAllowedTags($this->getAllowedTags()); + + return $sanitizer->sanitize($svg); + } + + private function getAllowedAttrs() + { + $attrs = $this->params->explode('allow_attrs', []); + + return new class($attrs) extends AllowedAttributes + { + private static $attrs = []; + + public function __construct($attrs) + { + self::$attrs = $attrs; + } + + public static function getAttributes() + { + return array_merge(parent::getAttributes(), self::$attrs); + } + }; + } + + private function getAllowedTags() + { + $tags = $this->params->explode('allow_tags', []); + + return new class($tags) extends AllowedTags + { + private static $tags = []; + + public function __construct($tags) + { + self::$tags = $tags; + } + + public static function getTags() + { + return array_merge(parent::getTags(), self::$tags); + } + }; + } }
tests/Tags/SvgTagTest.php+71 −1 modified@@ -4,6 +4,7 @@ use Illuminate\Support\Facades\File; use Statamic\Facades\Parse; +use Statamic\View\Antlers\Language\Utilities\StringUtilities; use Tests\TestCase; class SvgTagTest extends TestCase @@ -17,7 +18,10 @@ public function setUp(): void private function tag($tag) { - return Parse::template($tag, []); + $output = Parse::template($tag, []); + + // Normalize whitespace and line breaks for testing ease. + return trim(StringUtilities::normalizeLineEndings($output)); } /** @test */ @@ -32,4 +36,70 @@ public function it_renders_svg_with_additional_params() { $this->assertStringStartsWith('<svg class="mb-2" xmlns="', $this->tag('{{ svg src="users" class="mb-2" }}')); } + + /** @test */ + public function it_sanitizes() + { + File::put(resource_path('xss.svg'), <<<'SVG' +<svg> + <path onload="loadxss" onclick="clickxss"></path> + <script>alert("xss")</script> + <foreignObject></foreignObject> + <mesh></mesh> +</svg> +SVG); + + $this->assertEquals(<<<'SVG' +<svg> + <path></path> +</svg> +SVG, + $this->tag('{{ svg src="xss" sanitize="true" }}') + ); + + $this->assertEquals(<<<'SVG' +<svg> + <path onclick="clickxss"></path> + <foreignObject></foreignObject> + <mesh></mesh> +</svg> +SVG, + $this->tag('{{ svg src="xss" sanitize="true" allow_tags="mesh|foreignObject" allow_attrs="onclick" }}') + ); + } + + /** @test */ + public function sanitizing_doesnt_add_xml_tag() + { + // Thes sanitizer package adds an xml tag by default. + // We want to make sure if there wasn't one to begin with, it doesn't add one. + + $svg = <<<'SVG' +<svg> + <path></path> +</svg> +SVG; + + File::put(resource_path('xmltag.svg'), $svg); + + $this->assertEquals($svg, $this->tag('{{ svg src="xmltag" sanitize="true" }}')); + } + + /** @test */ + public function sanitizing_doesnt_remove_an_xml_tag() + { + // Thes sanitizer package adds an xml tag by default. + // We want to make sure that we haven't configured it to remove it if we wanted it there to begin with. + + $svg = <<<'SVG' +<?xml version="1.0" encoding="UTF-8"?> +<svg> + <path></path> +</svg> +SVG; + + File::put(resource_path('xmltag.svg'), $svg); + + $this->assertEquals($svg, $this->tag('{{ svg src="xmltag" sanitize="true" }}')); + } }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-6r5g-cq4q-327gghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-36828ghsaADVISORY
- github.com/statamic/cms/blob/f806b6b007ddcf066082eef175653c5beaa96d60/src/Http/Controllers/CP/Fieldtypes/FilesFieldtypeController.phpghsax_refsource_MISCWEB
- github.com/statamic/cms/blob/f806b6b007ddcf066082eef175653c5beaa96d60/src/Tags/Svg.phpghsax_refsource_MISCWEB
- github.com/statamic/cms/commit/c714893ad92de6e5ede17b501003441af505b30dghsax_refsource_MISCWEB
- github.com/statamic/cms/pull/8408ghsax_refsource_MISCWEB
- github.com/statamic/cms/releases/tag/v4.10.0ghsax_refsource_MISCWEB
- github.com/statamic/cms/security/advisories/GHSA-6r5g-cq4q-327gghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.