Skip to content

Commit 47a9c72

Browse files
committed
fix: svg sanatize.
1 parent 4b4608e commit 47a9c72

File tree

2 files changed

+71
-36
lines changed

2 files changed

+71
-36
lines changed

packages/Webkul/Admin/src/Http/Controllers/TinyMCEController.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Webkul\Admin\Http\Controllers;
44

5+
use Illuminate\Http\JsonResponse;
6+
use Illuminate\Http\UploadedFile;
57
use Illuminate\Support\Facades\Storage;
68
use Webkul\Core\Traits\Sanitizer;
79

@@ -11,17 +13,13 @@ class TinyMCEController extends Controller
1113

1214
/**
1315
* Storage folder path.
14-
*
15-
* @var string
1616
*/
17-
private $storagePath = 'tinymce';
17+
private string $storagePath = 'tinymce';
1818

1919
/**
2020
* Upload file from tinymce.
21-
*
22-
* @return void
2321
*/
24-
public function upload()
22+
public function upload(): JsonResponse
2523
{
2624
$media = $this->storeMedia();
2725

@@ -36,20 +34,24 @@ public function upload()
3634

3735
/**
3836
* Store media.
39-
*
40-
* @return array
4137
*/
42-
public function storeMedia()
38+
public function storeMedia(): array
4339
{
4440
if (! request()->hasFile('file')) {
4541
return [];
4642
}
4743

4844
$file = request()->file('file');
4945

50-
$path = $file->store($this->storagePath);
46+
if (! $file instanceof UploadedFile) {
47+
return [];
48+
}
49+
50+
$filename = md5($file->getClientOriginalName().time()).'.'.$file->getClientOriginalExtension();
51+
52+
$path = $file->storeAs($this->storagePath, $filename);
5153

52-
$this->sanitizeSVG($path, $file->getMimeType());
54+
$this->sanitizeSVG($path, $file);
5355

5456
return [
5557
'file' => $path,

packages/Webkul/Core/src/Traits/Sanitizer.php

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,80 @@
22

33
namespace Webkul\Core\Traits;
44

5+
use enshrined\svgSanitize\data\AllowedAttributes;
6+
use enshrined\svgSanitize\data\AllowedTags;
57
use enshrined\svgSanitize\Sanitizer as MainSanitizer;
8+
use Exception;
9+
use Illuminate\Http\UploadedFile;
610
use Illuminate\Support\Facades\Storage;
711

12+
/**
13+
* Trait for sanitizing SVG uploads to prevent security vulnerabilities.
14+
*/
815
trait Sanitizer
916
{
1017
/**
11-
* List of mime types which needs to check.
18+
* Sanitize an SVG file to remove potentially malicious content.
1219
*/
13-
public $mimeTypes = [
14-
'image/svg',
15-
'image/svg+xml',
16-
];
17-
18-
/**
19-
* Sanitize SVG file.
20-
*
21-
* @param string $path
22-
* @return void
23-
*/
24-
public function sanitizeSVG($path, $mimeType)
20+
public function sanitizeSvg(string $path, UploadedFile $file): void
2521
{
26-
if ($this->checkMimeType($mimeType)) {
27-
/* sanitizer instance */
22+
if (! $this->isSvgFile($file)) {
23+
return;
24+
}
25+
26+
try {
27+
$svgContent = Storage::get($path);
28+
29+
if (! $svgContent) {
30+
return;
31+
}
32+
2833
$sanitizer = new MainSanitizer;
34+
$sanitizer->setAllowedAttrs(new AllowedAttributes);
35+
$sanitizer->setAllowedTags(new AllowedTags);
36+
37+
$sanitizer->minify(true);
38+
$sanitizer->removeRemoteReferences(true);
39+
$sanitizer->removeXMLTag(true);
40+
41+
$sanitizer->setXMLOptions(LIBXML_NONET | LIBXML_NOBLANKS);
42+
43+
$sanitizedContent = $sanitizer->sanitize($svgContent);
44+
45+
if ($sanitizedContent === false) {
46+
$patterns = [
47+
'/<script\b[^>]*>(.*?)<\/script>/is',
48+
'/\bon\w+\s*=\s*["\'][^"\']*["\']/i',
49+
'/javascript\s*:/i',
50+
'/data\s*:[^,]*base64/i',
51+
];
52+
53+
$sanitizedContent = $svgContent;
54+
55+
foreach ($patterns as $pattern) {
56+
$sanitizedContent = preg_replace($pattern, '', $sanitizedContent);
57+
}
58+
59+
Storage::put($path, $sanitizedContent);
60+
61+
return;
62+
}
63+
64+
$sanitizedContent = preg_replace('/(<script.*?>.*?<\/script>)|(\son\w+\s*=\s*["\'][^"\']*["\'])/is', '', $sanitizedContent);
2965

30-
/* grab svg file */
31-
$dirtySVG = Storage::get($path);
66+
Storage::put($path, $sanitizedContent);
67+
} catch (Exception $e) {
68+
report($e->getMessage());
3269

33-
/* save sanitized svg */
34-
Storage::put($path, $sanitizer->sanitize($dirtySVG));
70+
Storage::delete($path);
3571
}
3672
}
3773

3874
/**
39-
* Sanitize SVG file.
40-
*
41-
* @param string $path
42-
* @return void
75+
* Check if the uploaded file is an SVG based on both extension and mime type.
4376
*/
44-
public function checkMimeType($mimeType)
77+
public function isSvgFile(UploadedFile $file): bool
4578
{
46-
return in_array($mimeType, $this->mimeTypes);
79+
return str_contains(strtolower($file->getClientOriginalExtension()), 'svg');
4780
}
4881
}

0 commit comments

Comments
 (0)