fix(share) : durcissement download (allowlist inline anti-XSS + nosniff) et masquage des erreurs SMB

This commit is contained in:
Matthieu
2026-06-03 17:42:36 +02:00
parent 74b6d298fb
commit 4ffa19e53f
2 changed files with 11 additions and 7 deletions
@@ -39,8 +39,8 @@ class ShareBrowseController extends AbstractController
$entries = $this->fileSource->dir($path);
} catch (ShareNotConfiguredException) {
return new JsonResponse(['error' => 'Share not configured.'], 409);
} catch (ShareConnectionException $e) {
return new JsonResponse(['error' => $e->getMessage()], 502);
} catch (ShareConnectionException) {
return new JsonResponse(['error' => 'Unable to reach the file share.'], 502);
}
return new JsonResponse([
@@ -48,17 +48,19 @@ class ShareDownloadController extends AbstractController
$stream = $this->fileSource->read($path);
} catch (ShareNotConfiguredException) {
return new Response('Share not configured.', 409);
} catch (ShareConnectionException $e) {
throw new NotFoundHttpException($e->getMessage());
} catch (ShareConnectionException) {
throw new NotFoundHttpException('File not found.');
}
$name = basename($path);
$extension = pathinfo($name, PATHINFO_EXTENSION);
$mime = MimeTypes::getDefault()->getMimeTypes($extension)[0] ?? 'application/octet-stream';
// SVG toujours en attachment (anti-XSS) ; sinon respecte le paramètre demandé.
$requested = 'attachment' === $request->query->get('disposition') ? 'attachment' : 'inline';
$disposition = 'image/svg+xml' === $mime ? HeaderUtils::DISPOSITION_ATTACHMENT : $requested;
// Anti-XSS : seuls des types non exécutables sont servis inline (images hors SVG, PDF).
// Tout le reste (HTML, SVG, octet-stream, etc.) est forcé en attachment, même si inline est demandé.
$inlineSafe = ('image/svg+xml' !== $mime && str_starts_with($mime, 'image/')) || 'application/pdf' === $mime;
$wantInline = 'attachment' !== $request->query->get('disposition');
$disposition = ($inlineSafe && $wantInline) ? HeaderUtils::DISPOSITION_INLINE : HeaderUtils::DISPOSITION_ATTACHMENT;
$response = new StreamedResponse(function () use ($stream): void {
if (is_resource($stream)) {
@@ -68,6 +70,8 @@ class ShareDownloadController extends AbstractController
});
$response->headers->set('Content-Type', $mime);
$response->headers->set('Content-Disposition', HeaderUtils::makeDisposition($disposition, $name));
// Empêche le navigateur de "deviner" un type exécutable à partir du contenu.
$response->headers->set('X-Content-Type-Options', 'nosniff');
return $response;
}