OroPlatform's pinned entity creation form shows pages of other users
Description
Authenticated users in OroPlatform can access page state data of other users' pinned pages via a pageId hash, fixed in 5.1.4.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Authenticated users in OroPlatform can access page state data of other users' pinned pages via a pageId hash, fixed in 5.1.4.
CVE-2023-45824 is an information disclosure vulnerability in OroPlatform, a PHP business application platform. A logged-in user can access the page state data of pinned pages belonging to other users by providing a specific pageId hash. The flaw exists in the PagestateController where the authorization check to verify that the requested page state belongs to the current user is missing.
An attacker who is authenticated to the application can exploit this by directly manipulating the pageId parameter in API calls to the page state endpoints. No special privileges are required beyond a standard user account; the attacker simply needs to know or guess the pageId hash of another user's pinned page. The commit reference shows the fix adds a check to ensure the retrieved page state entity belongs to the requesting user before returning the state data [1][4].
Successful exploitation allows an attacker to view sensitive information that may be stored in the page state of other users' pinned pages. This could include form data, UI state, or other business data visible through the pinned page's configuration. The vulnerability does not allow modification or deletion of data, only unauthorized viewing of state data [2].
The vulnerability is fixed in OroPlatform version 5.1.4. The patch introduces a verification step in the PagestateController to ensure that the state being retrieved is owned by the requesting user; if not, a 404 Not Found response is returned [1][4]. Users are advised to upgrade to the patched version. There is no mention of a workaround for earlier versions.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
oro/platformPackagist | >= 5.1.0, < 5.1.4 | 5.1.4 |
oro/platformPackagist | >= 5.0.0, <= 5.0.12 | — |
oro/platformPackagist | >= 4.2.0, <= 4.2.10 | — |
Affected products
2- oroinc/platformv5Range: >=4.2.0, <=4.2.10
Patches
1cf94df7595afBB-22832: Multifile attribute is shown on product visibility page in back-office - 5.1 (#36428)
6 files changed · +85 −11
src/Oro/Bundle/AttachmentBundle/EventListener/MultiFileBlockListener.php+43 −9 modified@@ -4,6 +4,10 @@ use Doctrine\Common\Util\ClassUtils; use Oro\Bundle\AttachmentBundle\Helper\FieldConfigHelper; +use Oro\Bundle\EntityConfigBundle\Attribute\Entity\AttributeFamilyAwareInterface; +use Oro\Bundle\EntityConfigBundle\Config\Id\FieldConfigId; +use Oro\Bundle\EntityConfigBundle\Entity\FieldConfigModel; +use Oro\Bundle\EntityConfigBundle\Manager\AttributeManager; use Oro\Bundle\EntityConfigBundle\Provider\ConfigProvider; use Oro\Bundle\EntityExtendBundle\Event\ValueRenderEvent; use Oro\Bundle\UIBundle\Event\BeforeFormRenderEvent; @@ -20,6 +24,9 @@ class MultiFileBlockListener // default priority for view pages const ADDITIONAL_SECTION_PRIORITY = 1200; + /** @var AttributeManager */ + private $attributeManager; + /** @var ConfigProvider */ private $entityConfigProvider; @@ -32,6 +39,11 @@ public function __construct(ConfigProvider $configProvider, TranslatorInterface $this->translator = $translator; } + public function setAttributeManager(AttributeManager $attributeManager): void + { + $this->attributeManager = $attributeManager; + } + public function onBeforeValueRender(ValueRenderEvent $event) { if (FieldConfigHelper::isMultiField($event->getFieldConfigId())) { @@ -53,8 +65,7 @@ public function onBeforeViewRender(BeforeViewRenderEvent $event) } $className = ClassUtils::getClass($event->getEntity()); - - $fieldConfigs = $this->entityConfigProvider->getIds($className); + $fieldConfigs = $this->getConfigs($event->getEntity()); if (!$fieldConfigs) { return; } @@ -66,9 +77,6 @@ public function onBeforeViewRender(BeforeViewRenderEvent $event) foreach ($fieldConfigs as $fieldConfig) { $fieldName = $fieldConfig->getFieldName(); - if (!FieldConfigHelper::isMultiField($fieldConfig)) { - continue; - } $config = $this->entityConfigProvider->getConfig($className, $fieldName); $blockKey = $fieldName . '_block_section'; @@ -103,7 +111,7 @@ public function onBeforeFormRender(BeforeFormRenderEvent $event) $className = ClassUtils::getClass($event->getEntity()); - $fieldConfigs = $this->entityConfigProvider->getIds($className); + $fieldConfigs = $this->getConfigs($event->getEntity()); if (!$fieldConfigs) { return; } @@ -115,9 +123,6 @@ public function onBeforeFormRender(BeforeFormRenderEvent $event) foreach ($fieldConfigs as $fieldConfig) { $fieldName = $fieldConfig->getFieldName(); - if (!FieldConfigHelper::isMultiField($fieldConfig)) { - continue; - } $config = $this->entityConfigProvider->getConfig($className, $fieldName); $newBlockKey = $fieldName . '_block_section'; @@ -139,6 +144,35 @@ public function onBeforeFormRender(BeforeFormRenderEvent $event) $event->setFormData($scrollData->getData()); } + /** + * @param object $entity + * + * @return FieldConfigModel[] + */ + private function getConfigs(object $entity): array + { + $configManager = $this->entityConfigProvider->getConfigManager(); + $className = ClassUtils::getClass($entity); + + $ids = $this->entityConfigProvider->getIds($className); + $multiIds = array_filter($ids, fn (FieldConfigId $id) => FieldConfigHelper::isMultiField($id)); + + if ($entity instanceof AttributeFamilyAwareInterface && $entity->getAttributeFamily()) { + $family = $entity->getAttributeFamily(); + $familyFilter = function (FieldConfigId $id) use ($configManager, $family, $className) { + $config = $configManager->getFieldConfig('attribute', $className, $id->getFieldName()); + + return $config->get('is_attribute') + ? $this->attributeManager->getAttributeByFamilyAndName($family, $id->getFieldName()) + : true; + }; + + $multiIds = array_filter($multiIds, $familyFilter); + } + + return $multiIds; + } + private function isFileOrImageField(string $type): bool { return in_array($type, [FieldConfigHelper::FILE_TYPE, FieldConfigHelper::IMAGE_TYPE], true);
src/Oro/Bundle/AttachmentBundle/Resources/config/services.yml+2 −0 modified@@ -171,6 +171,8 @@ services: arguments: - '@oro_entity_config.provider.entity' - '@translator' + calls: + - ['setAttributeManager', ['@oro_entity_config.manager.attribute_manager']] tags: - { name: kernel.event_listener, event: entity_form.render.before, method: onBeforeFormRender, priority: -260 } - { name: kernel.event_listener, event: entity_view.render.before, method: onBeforeViewRender, priority: -260 }
src/Oro/Bundle/AttachmentBundle/Tests/Unit/EventListener/MultiFileBlockListenerTest.php+10 −1 modified@@ -6,6 +6,7 @@ use Oro\Bundle\AttachmentBundle\Tests\Unit\Stub\Entity\TestEntity1; use Oro\Bundle\EntityConfigBundle\Config\Config; use Oro\Bundle\EntityConfigBundle\Config\Id\FieldConfigId; +use Oro\Bundle\EntityConfigBundle\Manager\AttributeManager; use Oro\Bundle\EntityConfigBundle\Provider\ConfigProvider; use Oro\Bundle\EntityExtendBundle\Event\ValueRenderEvent; use Oro\Bundle\UIBundle\Event\BeforeFormRenderEvent; @@ -26,15 +27,23 @@ class MultiFileBlockListenerTest extends \PHPUnit\Framework\TestCase /** @var ConfigProvider|\PHPUnit\Framework\MockObject\MockObject */ private $configProvider; + /** @var AttributeManager|\PHPUnit\Framework\MockObject\MockObject */ + private $attributeManager; + /** @var MultiFileBlockListener */ private $listener; protected function setUp(): void { $this->configProvider = $this->createMock(ConfigProvider::class); $this->translator = $this->createMock(TranslatorInterface::class); + $this->attributeManager = $this->createMock(AttributeManager::class); - $this->listener = new MultiFileBlockListener($this->configProvider, $this->translator); + $this->listener = new MultiFileBlockListener( + $this->configProvider, + $this->translator, + ); + $this->listener->setAttributeManager($this->attributeManager); } public function testOnBeforeValueRender()
src/Oro/Bundle/UIBundle/Event/BeforeFormRenderEvent.php+12 −0 modified@@ -34,6 +34,8 @@ class BeforeFormRenderEvent extends Event */ protected $twigEnvironment; + protected ?string $pageId = null; + /** * @param FormView $form * @param array $formData @@ -48,6 +50,11 @@ public function __construct(FormView $form, array $formData, Environment $twigEn $this->entity = $entity; } + public function setPageId(?string $pageId = null): void + { + $this->pageId = $pageId; + } + /** * @return FormView */ @@ -84,4 +91,9 @@ public function getEntity() { return $this->entity; } + + public function getPageId(): ?string + { + return $this->pageId; + } }
src/Oro/Bundle/UIBundle/Resources/views/actions/update.html.twig+1 −1 modified@@ -177,7 +177,7 @@ {% endif %} <div class="layout-content"> {% block content_data %} - {% set data = oro_form_process(data, form, entity) %} + {% set data = oro_form_process_with_page_identifier(data, form, entity, id) %} {% if entity and data is defined and data.dataBlocks is defined %} {% set dataBlocks = data.dataBlocks %}
src/Oro/Bundle/UIBundle/Twig/UiExtension.php+17 −0 modified@@ -135,6 +135,11 @@ public function getFunctions() [$this, 'processForm'], ['needs_environment' => true] ), + new TwigFunction( + 'oro_form_process_with_page_identifier', + [$this, 'processFormWithPageIdentifier'], + ['needs_environment' => true] + ), new TwigFunction( 'oro_form_additional_data', [$this, 'renderAdditionalData'], @@ -213,7 +218,19 @@ public function processForm(TwigEnvironment $environment, array $data, FormView { $event = new BeforeFormRenderEvent($form, $data, $environment, $entity); $this->getEventDispatcher()->dispatch($event, Events::BEFORE_UPDATE_FORM_RENDER); + return $event->getFormData(); + } + public function processFormWithPageIdentifier( + TwigEnvironment $environment, + array $data, + FormView $form, + ?object $entity = null, + ?string $pageId = null + ): array { + $event = new BeforeFormRenderEvent($form, $data, $environment, $entity); + $event->setPageId($pageId); + $this->getEventDispatcher()->dispatch($event, Events::BEFORE_UPDATE_FORM_RENDER); return $event->getFormData(); }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-vxq2-p937-3px3ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-45824ghsaADVISORY
- github.com/oroinc/platform/commit/cf94df7595afca052796e26b299d2ce031e289cdghsax_refsource_MISCWEB
- github.com/oroinc/platform/security/advisories/GHSA-vxq2-p937-3px3ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.