File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 55<script >
66import { defineAsyncComponent } from ' vue' ;
77import { data_get } from ' ../bootstrap/globals.js'
8+ import DOMPurify from ' dompurify' ;
89
910export default {
1011
@@ -53,13 +54,13 @@ export default {
5354 evaluateIcon () {
5455 if (this .customIcon ) {
5556 return defineAsyncComponent (() => {
56- return new Promise (resolve => resolve ({ template: this .customIcon }));
57+ return new Promise (resolve => resolve ({ template: DOMPurify . sanitize ( this .customIcon ) }));
5758 });
5859 }
5960
6061 if (this .name .startsWith (' <svg' )) {
6162 return defineAsyncComponent (() => {
62- return new Promise (resolve => resolve ({ template: this .name }));
63+ return new Promise (resolve => resolve ({ template: DOMPurify . sanitize ( this .name ) }));
6364 });
6465 }
6566
Original file line number Diff line number Diff line change 55 <div class =" flex items-center flex-1 p-2 rtl:mr-2 ltr:ml-2 text-xs leading-normal" >
66 <div class =" flex items-center flex-1" :class =" { 'opacity-50': isHidden || isInHiddenSection }" >
77 <template v-if =" ! isSection && ! isChild " >
8- <i v-if =" isAlreadySvg" class =" w-4 h-4 rtl:ml-2 ltr:mr-2" v-html =" icon" ></i >
9- <svg-icon v-else class =" w-4 h-4 rtl:ml-2 ltr:mr-2" :name =" 'light/'+icon" />
8+ <svg-icon
9+ class =" w-4 h-4 rtl:ml-2 ltr:mr-2"
10+ :name =" isAlreadySvg ? icon : 'light/'+icon"
11+ />
1012 </template >
1113
1214 <a
Original file line number Diff line number Diff line change 33namespace Statamic \CP \Navigation ;
44
55use Illuminate \Support \Collection ;
6+ use Rhukster \DomSanitizer \DOMSanitizer ;
67use Statamic \Facades \CP \Nav ;
78use Statamic \Facades \URL ;
89use Statamic \Statamic ;
@@ -200,7 +201,22 @@ public function svg()
200201 {
201202 $ value = $ this ->icon () ?? 'entries ' ;
202203
203- return Str::startsWith ($ value , '<svg ' ) ? $ value : Statamic::svg ('icons/light/ ' .$ value );
204+ $ svg = Str::startsWith ($ value , '<svg ' ) ? $ value : Statamic::svg ('icons/light/ ' .$ value );
205+
206+ return $ this ->sanitizeSvg ($ svg );
207+ }
208+
209+ private function sanitizeSvg (string $ svg ): string
210+ {
211+ try {
212+ $ sanitizer = new DOMSanitizer (DOMSanitizer::SVG );
213+
214+ return $ sanitizer ->sanitize ($ svg , [
215+ 'remove-xml-tags ' => ! Str::startsWith ($ svg , '<?xml ' ),
216+ ]);
217+ } catch (\Throwable $ e ) {
218+ return '' ;
219+ }
204220 }
205221
206222 /**
Original file line number Diff line number Diff line change @@ -130,14 +130,15 @@ public function it_can_create_a_nav_item_with_a_custom_inline_svg_icon()
130130 $ this ->actingAs (tap (User::make ()->makeSuper ())->save ());
131131
132132 Nav::utilities ('Test ' )
133- ->icon ('<svg><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /></svg> ' );
133+ ->icon ('<svg onerror="foo" ><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /></svg> ' );
134134
135135 $ item = $ this ->build ()->get ('Utilities ' )->last ();
136136
137- $ expected = '<svg><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /></svg> ' ;
137+ $ expectedIcon = '<svg onerror="foo"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /></svg> ' ;
138+ $ this ->assertEquals ($ expectedIcon , $ item ->icon ());
138139
139- $ this -> assertEquals ( $ expected , $ item -> icon ()) ;
140- $ this ->assertEquals ($ expected , $ item ->svg ());
140+ $ expectedSvg = ' <svg><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red"/></svg> ' ;
141+ $ this ->assertEquals ($ expectedSvg , $ item ->svg ());
141142 }
142143
143144 #[Test]
You can’t perform that action at this time.
0 commit comments