diff --git a/typo3/sysext/core/Classes/Resource/ProcessedFile.php b/typo3/sysext/core/Classes/Resource/ProcessedFile.php
index a3dce434486d004c9683396bbf2f3ace862f8c0f..6fee23181cacbbaca586cc6e058726fba4ffe6f6 100644
--- a/typo3/sysext/core/Classes/Resource/ProcessedFile.php
+++ b/typo3/sysext/core/Classes/Resource/ProcessedFile.php
@@ -16,6 +16,7 @@
 namespace TYPO3\CMS\Core\Resource;
 
 use TYPO3\CMS\Core\Resource\Processing\TaskTypeRegistry;
+use TYPO3\CMS\Core\Resource\Service\ConfigurationService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 
@@ -143,6 +144,7 @@ class ProcessedFile extends AbstractFile
     protected function reconstituteFromDatabaseRecord(array $databaseRow)
     {
         $this->taskType = $this->taskType ?: $databaseRow['task_type'];
+        // @todo In case the original configuration contained file objects the reconstitution fails. See ConfigurationService->serialize()
         $this->processingConfiguration = $this->processingConfiguration ?: unserialize($databaseRow['configuration'] ?? '');
 
         $this->originalFileSha1 = $databaseRow['originalfilesha1'];
@@ -399,7 +401,7 @@ class ProcessedFile extends AbstractFile
             $properties['name'] = $this->getName();
         }
 
-        $properties['configuration'] = serialize($this->processingConfiguration);
+        $properties['configuration'] = (new ConfigurationService())->serialize($this->processingConfiguration);
 
         return array_merge($properties, [
             'storage' => $this->getStorage()->getUid(),
diff --git a/typo3/sysext/core/Classes/Resource/ProcessedFileRepository.php b/typo3/sysext/core/Classes/Resource/ProcessedFileRepository.php
index 46b39b42b32c98bb3256ad3a0026728c0aeab358..d998a4d2ab3ef9d5962da80f70ade4c12dd112e5 100644
--- a/typo3/sysext/core/Classes/Resource/ProcessedFileRepository.php
+++ b/typo3/sysext/core/Classes/Resource/ProcessedFileRepository.php
@@ -20,6 +20,7 @@ use Psr\Log\LoggerAwareTrait;
 use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;
+use TYPO3\CMS\Core\Resource\Service\ConfigurationService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -240,7 +241,7 @@ class ProcessedFileRepository extends AbstractRepository implements LoggerAwareI
                 $queryBuilder->expr()->eq('task_type', $queryBuilder->createNamedParameter($taskType)),
                 $queryBuilder->expr()->eq(
                     'configurationsha1',
-                    $queryBuilder->createNamedParameter(sha1(serialize($configuration)))
+                    $queryBuilder->createNamedParameter(sha1((new ConfigurationService())->serialize($configuration)))
                 )
             )
             ->executeQuery()
diff --git a/typo3/sysext/core/Classes/Resource/Processing/AbstractTask.php b/typo3/sysext/core/Classes/Resource/Processing/AbstractTask.php
index 8a66263876d632e5d52992d3e201354b02894c77..8a41c9d3e840529818854f4667b44960a8f0660c 100644
--- a/typo3/sysext/core/Classes/Resource/Processing/AbstractTask.php
+++ b/typo3/sysext/core/Classes/Resource/Processing/AbstractTask.php
@@ -18,6 +18,7 @@ namespace TYPO3\CMS\Core\Resource\Processing;
 use TYPO3\CMS\Core\Resource;
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\ProcessedFile;
+use TYPO3\CMS\Core\Resource\Service\ConfigurationService;
 
 /**
  * Abstract base implementation of a task.
@@ -91,7 +92,7 @@ abstract class AbstractTask implements TaskInterface
         return [
             $this->getSourceFile()->getUid(),
             $this->getType() . '.' . $this->getName() . $this->getSourceFile()->getModificationTime(),
-            serialize($this->configuration),
+            (new ConfigurationService())->serialize($this->configuration),
         ];
     }
 
diff --git a/typo3/sysext/core/Classes/Resource/Service/ConfigurationService.php b/typo3/sysext/core/Classes/Resource/Service/ConfigurationService.php
new file mode 100644
index 0000000000000000000000000000000000000000..a8f45eabf2cc4c470be91374e3e19a661760a481
--- /dev/null
+++ b/typo3/sysext/core/Classes/Resource/Service/ConfigurationService.php
@@ -0,0 +1,55 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Core\Resource\Service;
+
+use TYPO3\CMS\Core\Resource\FileInterface;
+
+/**
+ * Resources can contain configurations: For example to define image dimensions or
+ * image masking. Resource configurations form part of the object identity and are
+ * used to create an object signature that itself is used to cache objects but NOT
+ * to reconstruct them. To prevent objects to be reconstructed they MUST NOT be
+ * serialized. This is why an object signature is obtained by serializing its array
+ * rather than serializing it directly. But attention...as well the objects array
+ * MUST NOT contain resource objects which could be the case when a configuration
+ * defines image masking. Here this service comes into play: it serializes any
+ * object configuration, as well those containing resources.
+ */
+class ConfigurationService
+{
+    public function serialize(array $configuration): string
+    {
+        return serialize($this->makeSerializable($configuration));
+    }
+
+    /**
+     * Recursively substitute file objects with their array representation.
+     */
+    protected function makeSerializable(array $configuration): array
+    {
+        return array_map(function ($value) {
+            if (is_array($value)) {
+                return $this->makeSerializable($value);
+            }
+            if ($value instanceof FileInterface) {
+                return $value->toArray();
+            }
+            return $value;
+        }, $configuration);
+    }
+}
diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/ProcessedFileTest.jpg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/ProcessedFileTest.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/typo3/sysext/core/Tests/Functional/Resource/ProcessedFileTest.php b/typo3/sysext/core/Tests/Functional/Resource/ProcessedFileTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..729f46e98367d97fb15049a234dd1a128b8e0bb7
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/Resource/ProcessedFileTest.php
@@ -0,0 +1,71 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Core\Tests\Functional\Resource;
+
+use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Resource\ProcessedFile;
+use TYPO3\CMS\Core\Resource\ResourceFactory;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
+
+class ProcessedFileTest extends FunctionalTestCase
+{
+    private const TEST_IMAGE = 'fileadmin/ProcessedFileTest.jpg';
+
+    /**
+     * @var array<string, non-empty-string>
+     */
+    protected array $pathsToProvideInTestInstance = [
+        'typo3/sysext/core/Tests/Functional/Resource/Fixtures/ProcessedFileTest.jpg' => 'fileadmin/ProcessedFileTest.jpg',
+    ];
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
+        $this->setUpBackendUser(1);
+        Bootstrap::initializeLanguageObject();
+    }
+
+    /**
+     * @test
+     */
+    public function processedFileArrayCanBeSerialized(): void
+    {
+        $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
+        $originalFile = $resourceFactory->retrieveFileOrFolderObject(self::TEST_IMAGE);
+        $someProcessedFile = new ProcessedFile(
+            $originalFile,
+            ProcessedFile::CONTEXT_IMAGECROPSCALEMASK,
+            []
+        );
+        $processedFile = new ProcessedFile(
+            $originalFile,
+            ProcessedFile::CONTEXT_IMAGECROPSCALEMASK,
+            [
+                'width' => '2000c',
+                'height' => '300c-60',
+                'm' => [
+                    'bgImg' => $someProcessedFile,
+                    'mask' => $someProcessedFile,
+                ],
+            ],
+        );
+        serialize($processedFile->toArray());
+    }
+}
diff --git a/typo3/sysext/core/Tests/Unit/Resource/Service/ConfigurationServiceTest.php b/typo3/sysext/core/Tests/Unit/Resource/Service/ConfigurationServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e25f1bf3372b1e44b1dcdb5092cdbd2874ceaf39
--- /dev/null
+++ b/typo3/sysext/core/Tests/Unit/Resource/Service/ConfigurationServiceTest.php
@@ -0,0 +1,55 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Core\Tests\Unit\Resource\Service;
+
+use TYPO3\CMS\Core\Resource\ProcessedFile;
+use TYPO3\CMS\Core\Resource\Service\ConfigurationService;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+class ConfigurationServiceTest extends UnitTestCase
+{
+    /**
+     * @test
+     */
+    public function serializeSubstitutesFileObject(): void
+    {
+        $fileMock = $this->createMock(ProcessedFile::class);
+        $fileMock->method('toArray')->willReturn(['id' => '1:test.jpg']);
+        $configuration = [
+            'width' => '2000c',
+            'height' => '300c-60',
+            'foo' => $fileMock,
+            'maskImages' => [
+                'maskImage' => $fileMock,
+                'backgroundImage' => $fileMock,
+                'bar' => 'bar1',
+            ],
+        ];
+        $expected = [
+            'width' => '2000c',
+            'height' => '300c-60',
+            'foo' => $fileMock->toArray(),
+            'maskImages' => [
+                'maskImage' => $fileMock->toArray(),
+                'backgroundImage' => $fileMock->toArray(),
+                'bar' => 'bar1',
+            ],
+        ];
+        self::assertSame(serialize($expected), (new ConfigurationService())->serialize($configuration));
+    }
+}