Security advisory GHSA-c8hj-w239-5gvf: pimcore/admin-ui-classic-bundle Full Path Disclosure via re-export document
Package: pimcore/admin-ui-classic-bundle (composer), vulnerable version: v1.2, fixed in: 1.2.1
CWE: CWE-209
Files changed by the fix:
src/Controller/Admin/Asset/AssetHelperController.php
src/Controller/Admin/DataObject/DataObjectHelperController.php

Fix diff:
diff --git a/src/Controller/Admin/Asset/AssetHelperController.php b/src/Controller/Admin/Asset/AssetHelperController.php
index 330d18715d..0e50e3e9a8 100644
--- a/src/Controller/Admin/Asset/AssetHelperController.php
+++ b/src/Controller/Admin/Asset/AssetHelperController.php
@@ -26,8 +26,8 @@
 use Pimcore\Bundle\AdminBundle\Model\GridConfigShare;
 use Pimcore\Bundle\AdminBundle\Tool;
 use Pimcore\Db;
+use Pimcore\File;
 use Pimcore\Loader\ImplementationLoader\Exception\UnsupportedException;
-use Pimcore\Localization\LocaleServiceInterface;
 use Pimcore\Logger;
 use Pimcore\Model\Asset;
 use Pimcore\Model\Element;
@@ -722,17 +722,13 @@ public function getExportJobsAction(Request $request, GridHelperService $gridHel
     /**
      * @Route("/do-export", name="pimcore_admin_asset_assethelper_doexport", methods={"POST"})
      *
-     * @param Request $request
-     * @param LocaleServiceInterface $localeService
-     *
-     * @return JsonResponse
+     * @throws FilesystemException
      */
-    public function doExportAction(Request $request, LocaleServiceInterface $localeService): JsonResponse
+    public function doExportAction(Request $request): JsonResponse
     {
-        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
+        $fileHandle = File::getValidFilename($request->get('fileHandle'));
         $ids = $request->get('ids');
-        $settings = $request->get('settings');
-        $settings = json_decode($settings, true);
+        $settings = json_decode($request->get('settings'), true);
         $delimiter = $settings['delimiter'] ?? ';';
         $language = str_replace('default', '', $request->get('language'));
 
@@ -752,27 +748,37 @@ public function doExportAction(Request $request, LocaleServiceInterface $localeS
 
         $csv = $this->getCsvData($request, $language, $list, $fields, $addTitles);
 
-        $storage = Storage::get('temp');
-        $csvFile = $this->getCsvFile($fileHandle);
+        try {
+            $storage = Storage::get('temp');
+            $csvFile = $this->getCsvFile($fileHandle);
 
-        $fileStream = $storage->readStream($csvFile);
+            $fileStream = $storage->readStream($csvFile);
 
-        $temp = tmpfile();
-        stream_copy_to_stream($fileStream, $temp, null, 0);
+            $temp = tmpfile();
+            stream_copy_to_stream($fileStream, $temp, null, 0);
 
-        $firstLine = true;
-        foreach ($csv as $line) {
-            if ($addTitles && $firstLine) {
-                $firstLine = false;
-                $line = implode($delimiter, $line) . "\r\n";
-                fwrite($temp, $line);
-            } else {
-                fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line)) . "\r\n");
+            $firstLine = true;
+            foreach ($csv as $line) {
+                if ($addTitles && $firstLine) {
+                    $firstLine = false;
+                    $line = implode($delimiter, $line) . "\r\n";
+                    fwrite($temp, $line);
+                } else {
+                    fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line)) . "\r\n");
+                }
             }
+            $storage->writeStream($csvFile, $temp);
+        } catch (UnableToReadFile $exception) {
+            Logger::err($exception->getMessage());
+
+            return $this->adminJson(
+                [
+                    'success' => false,
+                    'message' => sprintf('export file not found: %s', $fileHandle)
+                ]
+            );
         }
 
-        $storage->writeStream($csvFile, $temp);
-
         return $this->adminJson(['success' => true]);
     }
 
@@ -860,7 +866,7 @@ protected function getCsvFile(string $fileHandle): string
     public function downloadCsvFileAction(Request $request): Response
     {
         $storage = Storage::get('temp');
-        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
+        $fileHandle = File::getValidFilename($request->get('fileHandle'));
         $csvFile = $this->getCsvFile($fileHandle);
 
         try {
@@ -893,7 +899,7 @@ public function downloadCsvFileAction(Request $request): Response
     public function downloadXlsxFileAction(Request $request, GridHelperService $gridHelperService): BinaryFileResponse
     {
         $storage = Storage::get('temp');
-        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
+        $fileHandle = File::getValidFilename($request->get('fileHandle'));
         $csvFile = $this->getCsvFile($fileHandle);
 
         try {
diff --git a/src/Controller/Admin/DataObject/DataObjectHelperController.php b/src/Controller/Admin/DataObject/DataObjectHelperController.php
index 7325c781e5..c897573035 100644
--- a/src/Controller/Admin/DataObject/DataObjectHelperController.php
+++ b/src/Controller/Admin/DataObject/DataObjectHelperController.php
@@ -26,9 +26,11 @@
 use Pimcore\Bundle\AdminBundle\Model\GridConfigShare;
 use Pimcore\Config;
 use Pimcore\Db;
+use Pimcore\File;
 use Pimcore\Localization\LocaleServiceInterface;
 use Pimcore\Logger;
 use Pimcore\Model\DataObject;
+use Pimcore\Model\DataObject\Listing;
 use Pimcore\Model\User;
 use Pimcore\Security\SecurityHelper;
 use Pimcore\Tool;
@@ -1283,20 +1285,17 @@ public function getExportJobsAction(Request $request, GridHelperService $gridHel
     /**
      * @Route("/do-export", name="doexport", methods={"POST"})
      *
-     * @param Request $request
-     * @param LocaleServiceInterface $localeService
-     * @param EventDispatcherInterface $eventDispatcher
-     *
-     * @return JsonResponse
-     *
-     * @throws \Exception
+     * @throws \Exception|FilesystemException
      */
-    public function doExportAction(Request $request, LocaleServiceInterface $localeService, EventDispatcherInterface $eventDispatcher): JsonResponse
+    public function doExportAction(
+        Request $request,
+        LocaleServiceInterface $localeService,
+        EventDispatcherInterface $eventDispatcher
+    ): JsonResponse
     {
-        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
+        $fileHandle = File::getValidFilename($request->get('fileHandle'));
         $ids = $request->get('ids');
-        $settings = $request->get('settings');
-        $settings = json_decode($settings, true);
+        $settings = json_decode($request->get('settings'), true);
         $delimiter = $settings['delimiter'] ?? ';';
         $header = $settings['header'] ?? 'title';
 
@@ -1308,13 +1307,13 @@ public function doExportAction(Request $request, LocaleServiceInterface $localeS
         $class = DataObject\ClassDefinition::getById($request->get('classId'));
 
         if (!$class) {
-            throw new \Exception('No class definition found');
+            throw new \InvalidArgumentException('No class definition found');
         }
 
         $className = $class->getName();
         $listClass = '\\Pimcore\\Model\\DataObject\\' . ucfirst($className) . '\\Listing';
 
-        /** @var \Pimcore\Model\DataObject\Listing $list */
+        /** @var Listing $list */
         $list = new $listClass();
 
         $quotedIds = [];
@@ -1340,56 +1339,72 @@ public function doExportAction(Request $request, LocaleServiceInterface $localeS
 
         $requestedLanguage = $this->extractLanguage($request);
 
-        $contextFromRequest = $request->get('context');
-        if ($contextFromRequest) {
-            $contextFromRequest = json_decode($contextFromRequest, true);
-        }
-
         $context = [
             'source' => 'pimcore-export',
         ];
 
-        if (is_array($contextFromRequest)) {
+        $contextFromRequest = $request->get('context');
+        if ($contextFromRequest) {
+            $contextFromRequest = json_decode($contextFromRequest, true);
             $context = array_merge($context, $contextFromRequest);
         }
 
-        $csv = DataObject\Service::getCsvData($requestedLanguage, $localeService, $list, $fields, $header, $addTitles, $context);
+        $csv = DataObject\Service::getCsvData(
+            $requestedLanguage,
+            $localeService,
+            $list,
+            $fields,
+            $header,
+            $addTitles,
+            $context
+        );
 
-        $storage = Storage::get('temp');
-        $csvFile = $this->getCsvFile($fileHandle);
-
-        $fileStream = $storage->readStream($csvFile);
-
-        $temp = tmpfile();
-        stream_copy_to_stream($fileStream, $temp, null, 0);
-
-        $firstLine = true;
+        try {
+            $storage = Storage::get('temp');
+            $csvFile = $this->getCsvFile($fileHandle);
 
-        if ($request->get('initial') && $header === 'no_header') {
-            array_shift($csv);
-            $firstLine = false;
-        }
+            $fileStream = $storage->readStream($csvFile);
 
-        $lineCount = count($csv);
+            $temp = tmpfile();
+            stream_copy_to_stream($fileStream, $temp, null, 0);
 
-        if (!$addTitles && $lineCount > 0) {
-            fwrite($temp, "\r\n");
-        }
+            $firstLine = true;
 
-        for ($i = 0; $i < $lineCount; $i++) {
-            $line = $csv[$i];
-            if ($addTitles && $firstLine) {
+            if ($request->get('initial') && $header === 'no_header') {
+                array_shift($csv);
                 $firstLine = false;
-                $line = implode($delimiter, $line);
-                fwrite($temp, $line);
-            } else {
-                fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line)));
             }
-            if ($i < $lineCount - 1) {
+
+            $lineCount = count($csv);
+
+            if (!$addTitles && $lineCount > 0) {
                 fwrite($temp, "\r\n");
             }
+
+            for ($i = 0; $i < $lineCount; $i++) {
+                $line = $csv[$i];
+                if ($addTitles && $firstLine) {
+                    $firstLine = false;
+                    $line = implode($delimiter, $line);
+                    fwrite($temp, $line);
+                } else {
+                    fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line)));
+                }
+                if ($i < $lineCount - 1) {
+                    fwrite($temp, "\r\n");
+                }
+            }
+            $storage->writeStream($csvFile, $temp);
+        } catch (UnableToReadFile $exception) {
+            Logger::err($exception->getMessage());
+
+            return $this->adminJson(
+                [
+                    'success' => false,
+                    'message' => sprintf('export file not found: %s', $fileHandle)
+                ]
+            );
         }
-        $storage->writeStream($csvFile, $temp);
 
         return $this->adminJson(['success' => true]);
     }
@@ -1412,7 +1427,7 @@ public function encodeFunc(string $value): string
     public function downloadCsvFileAction(Request $request): Response
     {
         $storage = Storage::get('temp');
-        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
+        $fileHandle = File::getValidFilename($request->get('fileHandle'));
         $csvFile = $this->getCsvFile($fileHandle);
 
         try {
@@ -1445,7 +1460,7 @@ public function downloadCsvFileAction(Request $request): Response
     public function downloadXlsxFileAction(Request $request, GridHelperService $gridHelperService): BinaryFileResponse
     {
         $storage = Storage::get('temp');
-        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
+        $fileHandle = File::getValidFilename($request->get('fileHandle'));
         $csvFile = $this->getCsvFile($fileHandle);
 
         try {