Skip to content

DynamicStorage.findProductRewriteByRequestPath() lacks entity_type filtering, causing CMS pages to be treated as products in category URLs #39996

Open
@rbouma

Description

@rbouma

Preconditions and environment

  • Magento version: 2.4.x (affects all versions with DynamicStorage)
  • Environment: Any Magento installation with:
    • CMS pages with URL rewrites (e.g., privacy-policy-cookie-restriction-mode)
    • Categories with URL rewrites (e.g., schroeven)
    • Catalog URL Rewrite module enabled
  • Modules: Default Magento installation (no third-party modules required to reproduce)
  • URL Structure: Category URLs with CMS page identifiers as suffixes

Steps to reproduce

Prerequisites Setup:

  1. Create Category:

    • Create a category with URL key schroeven
    • Note the category entity_id (e.g., ID = 48)
  2. Create CMS Page:

    • Create a CMS page with identifier privacy-policy-cookie-restriction-mode
    • Note the CMS page entity_id (e.g., ID = 4)
  3. Create Product with Matching ID:

    • Create a product with entity_id = 4 (same as CMS page ID)
    • This is crucial - the product ID must match the CMS page ID
    • Assign this product to the schroeven category (ID 48)
    • Ensure the product is enabled and visible
  4. System Maintenance:

    bin/magento indexer:reindex
    bin/magento cache:clean
    bin/magento cache:flush

Reproduction Steps:

  1. Verify URL rewrites exist in database:

    -- Should show CMS page rewrite
    SELECT * FROM url_rewrite WHERE request_path = 'privacy-policy-cookie-restriction-mode';
    -- Should show category rewrite  
    SELECT * FROM url_rewrite WHERE request_path = 'schroeven.html';
  2. Navigate to malformed URL: /schroeven/privacy-policy-cookie-restriction-mode

  3. Observe the response

Why This Setup Is Required:

  • DynamicStorage extracts privacy-policy-cookie-restriction-mode
  • Finds CMS page with entity_id=4 (but treats it as product_id=4)
  • Checks if product_id=4 can be shown in category_id=48 using ProductResource::canBeShowInCategory(4, 48)
  • Since product ID 4 IS assigned to category 48, the check passes
  • DynamicStorage creates: /cms/page/view/page_id/4/category/48

Expected result

The URL /schroeven/privacy-policy-cookie-restriction-mode should return HTTP 404 because:

  • It's not a valid product URL pattern
  • It's not a valid category URL
  • It's not a valid CMS page URL
  • This malformed URL pattern should not resolve to any content

Actual result

The URL /schroeven/privacy-policy-cookie-restriction-mode returns HTTP 200 and serves the CMS page content with category context.

Root Cause Analysis:
The issue occurs in vendor/magento/module-catalog-url-rewrite/Model/Storage/DynamicStorage.php:

  1. Method findProductRewriteByRequestPath() extracts privacy-policy-cookie-restriction-mode from the URL
  2. It queries url_rewrite table WITHOUT filtering by entity_type
  3. Query finds the CMS page URL rewrite (entity_type = 'cms-page')
  4. DynamicStorage treats the CMS page as if it's a product
  5. Creates malformed target path: /cms/page/view/page_id/X/category/Y
  6. UrlRewrite Router serves this as valid content

Problematic Code (line ~147):

$productFromDb = $this->connection->fetchRow($this->prepareSelect($data));

The $data array only contains request_path and store_id - missing entity_type = 'product' filter.

Additional information

Database Evidence:

-- This query shows the CMS page that gets incorrectly matched
SELECT * FROM url_rewrite WHERE request_path = 'privacy-policy-cookie-restriction-mode';
-- Returns: entity_type='cms-page', entity_id=4, target_path='cms/page/view/page_id/4'

Debug Logs:
When processing /schroeven/privacy-policy-cookie-restriction-mode:

  1. UrlRewrite Router calls DynamicStorage
  2. DynamicStorage finds CMS page data (should only find products)
  3. Router creates Forward action to /cms/page/view/page_id/4/category/48

Affected Code Files:

  • vendor/magento/module-catalog-url-rewrite/Model/Storage/DynamicStorage.php (lines 140-200)
  • Method: findProductRewriteByRequestPath()

Suggested Fix:
Add entity_type filtering in the database query:

// Before querying for "product" data, ensure we only get products
$data[UrlRewrite::ENTITY_TYPE] = 'product';
$productFromDb = $this->connection->fetchRow($this->prepareSelect($data));

Security Impact: None - this is a URL routing issue, not a security vulnerability.

Performance Impact: Minimal - affects only specific URL patterns.

Workaround: Plugin on UrlRewrite Router to block malformed URL patterns before they reach DynamicStorage.

Release note

Fixed DynamicStorage URL rewrite query to properly filter by entity_type, preventing CMS pages from being incorrectly processed as products in category URL contexts.

Triage and priority

  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

Metadata

Metadata

Labels

Issue: needs updateAdditional information is require, waiting for responseReported on 2.4.xIndicates original Magento version for the Issue report.

Type

No type

Projects

Status

Needs Update

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions