or onload=""
* payloads. It isn't. The upload-time sanitizer strips both shapes
* before the file reaches disk, but the report was accurate about
* the inline-serving path, so this test locks in the upload-time
* sanitization so a future refactor can't quietly remove the SVG
* branch and reintroduce the exploit chain.
*/
class SvgUploadSanitizationTest extends TestCase
{
private array $tempFiles = [];
protected function setUp(): void
{
parent::setUp();
Storage::fake();
}
protected function tearDown(): void
{
foreach ($this->tempFiles as $path) {
@unlink($path);
}
parent::tearDown();
}
private function realUpload(string $clientName, string $content): UploadedFile
{
// A real temp file is required for finfo to sniff the MIME
// correctly. UploadedFile::fake() derives its mime from the
// filename, which would trivially "pass" the SVG detection
// without exercising the real sanitize path.
$path = tempnam(sys_get_temp_dir(), 'snipeit_svg_');
file_put_contents($path, $content);
$this->tempFiles[] = $path;
return new UploadedFile($path, $clientName, null, null, true);
}
public function test_svg_upload_strips_inline_script_element(): void
{
$malicious = <<<'SVG'
SVG;
$upload = $this->realUpload('malicious.svg', $malicious);
$storedName = (new UploadFileRequest)->handleFile('private_uploads/assets/', 'asset-1', $upload);
$storedContents = Storage::get('private_uploads/assets/'.$storedName);
$this->assertStringNotContainsString('