# CVE-2026-40098: magento-lts — Fixed in 20.17.0

🐘 Packagist

Not in CISA KEV

# CVE-2026-40098 — magento-lts

[Fix: OpenMage/magento-lts#5446](https://github.com/OpenMage/magento-lts/pull/5446)

CVE-2026-40098 is a CWE-862 vulnerability in openmage/magento-lts. A fix is available for openmage/magento-lts — see the affected versions and patch details below.

OpenMage LTS imports cross-user wishlist item via shared wishlist code, leading to private option disclosure and file-disclosure variant

Also known as[GHSA-665x-ppc4-685w](/vulnerability/GHSA-665x-ppc4-685w)

Published

Apr 20, 2026

Updated

Oct 28, 2026

Affected

1 pkg

Patched

1 / 1

Exploits

None indexed

Exploitation data as of Nov 10, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

## Exploitation Status

### Proof-of-concept exploit code exists

-   CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-40098.

## EPSS Exploitation Probability

[via FIRST.org ↗](https://www.first.org/epss/)

0.2%probability of exploitation in next 30 days

Lower Risk0.00%

Lower risk than most CVEs7th percentile — riskier than 7% of all scored CVEsHighest risk

0.00%0.25%0.50%0.75%0.0%0.2%May 26Sep 26Nov 26

Probability of exploitation in the next 30 days, from [FIRST.org EPSS](https://www.first.org/epss/).

## Real-World Exposure

1 pkg affected

🐘`openmage/magento-lts`

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.

## Description

## Cross-user wishlist item import via shared wishlist code, leading to private option disclosure and file-disclosure variant

### Summary

The shared wishlist add-to-cart endpoint authorizes access with a public `sharing_code`, but loads the acted-on wishlist item by a separate global `wishlist_item_id` and never verifies that the item belongs to the shared wishlist referenced by that code.

This lets an attacker use:

-   a valid shared wishlist code for wishlist A
-   a wishlist item ID belonging to victim wishlist B

to import victim item B into the attacker's cart through the shared wishlist flow for wishlist A.

Because the victim item's stored `buyRequest` is reused during cart import, the victim's private custom-option data is copied into the attacker's quote. If the product uses a file custom option, this can be elevated to cross-user file disclosure because the imported file metadata is preserved and the download endpoint is not ownership-bound.

### Vulnerability Type

-   Broken object-level authorization / IDOR
-   Cross-user data disclosure
-   Cross-user file disclosure variant

### Root Cause

In `app/code/core/Mage/Wishlist/controllers/SharedController.php`, the shared flow does:

```
$item = Mage::getModel('wishlist/item')->load($itemId);
$wishlist = Mage::getModel('wishlist/wishlist')->loadByCode($code);
...
$item->addToCart($cart);
```

Relevant lines:

-   `SharedController.php:86` loads the wishlist item by global ID
-   `SharedController.php:87` loads the wishlist by shared code
-   `SharedController.php:99` imports the item into cart

There is no check that:

```
$item->getWishlistId() == $wishlist->getId()
```

The safe owner flow in `app/code/core/Mage/Wishlist/controllers/IndexController.php:521-528` does preserve this binding by deriving the wishlist from `item->getWishlistId()`.

The imported item keeps its original `buyRequest` because `app/code/core/Mage/Wishlist/Model/Item.php:370-372` passes that stored request directly into:

```
$cart->addProduct($product, $buyRequest);
```

### Security Impact

#### Baseline impact

An attacker can import another user's private wishlist item into the attacker's own cart, using an unrelated shared wishlist code.

This is a clear cross-user authorization bypass. The victim item's private configuration is copied into the attacker's quote, including custom-option values such as personalized text.

#### Stronger variant: cross-user file disclosure

If the victim item contains a custom option of type `file`, the imported quote item preserves file metadata such as:

-   `quote_path`
-   `order_path`
-   `secret_key`

The file option renderer in `app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php:547-552` generates a download URL from:

-   the imported `sales/quote_item_option` ID
-   the preserved `secret_key`

The downloader in `app/code/core/Mage/Sales/controllers/DownloadController.php:150-185`:

-   loads quote item option by global ID
-   verifies only product option type and `secret_key`
-   reads the file from `order_path` or `quote_path`

It does not verify ownership of the quote item, order, or original wishlist item. This creates a cross-user file disclosure path once victim file metadata has been imported.

### Steps To Reproduce

#### Lab data

-   shared wishlist A:
    -   `wishlist_id = 1`
    -   `customer_id = 2`
    -   `sharing_code = 6376bb8c37a09c2de3664bd8cdc16412`
-   victim wishlist B:
    -   `wishlist_id = 2`
    -   `customer_id = 3`
-   victim item:
    -   `wishlist_item_id = 1`
    -   `wishlist_id = 2`
    -   `product_id = 2`
-   victim private text option marker:
    -   `VICTIM-MARKER-49040822`

#### Reproduction

Send:

```
GET /wishlist/shared/cart/?code=6376bb8c37a09c2de3664bd8cdc16412&item=1
```

Where:

-   `code` belongs to shared wishlist A
-   `item=1` belongs to victim wishlist B

#### Expected result

The request should be rejected because the item does not belong to the shared wishlist referenced by the `sharing_code`.

#### Actual result

The application imports victim item `1` into the attacker's quote anyway.

### Verified Evidence

#### Baseline variant

Previously verified at quote/option level in lab:

```
option_1 = VICTIM-MARKER-49040822
```

This shows that the attacker's cart received victim-private custom-option data from another user's wishlist item.

#### File-disclosure variant

Previously verified in lab after importing a victim file-option payload:

```
/sales/download/downloadCustomOption/id/9/key/86fca9b61c0b891b52fb/
```

This URL was generated from imported quote item option data containing the victim file metadata and secret key.

### Why This Is A Valid Bug

This is not a timing issue and does not depend on non-default security settings.

The bug is a direct authorization failure:

-   authorization is based on wishlist A's share code
-   the acted-on object is item B from another wishlist
-   there is no item-to-wishlist binding check
-   victim-controlled item state is then copied into attacker-controlled cart state

That is a broken object-level authorization issue with clear cross-user impact.

### Remediation

In `SharedController::cartAction()`, reject any request where the loaded item does not belong to the wishlist loaded from the share code:

```
$item = Mage::getModel('wishlist/item')->load($itemId);
$wishlist = Mage::getModel('wishlist/wishlist')->loadByCode($code);

if (!$item->getId() || !$wishlist->getId() || (int) $item->getWishlistId() !== (int) $wishlist->getId()) {
    return $this->_forward('noRoute');
}
```

Defense in depth:

-   bind `sales/download/downloadCustomOption` to the current quote/order owner instead of trusting only `id + secret_key`

## Affected Packages

1 total 1 fixed

Ecosystem

Package

Vulnerable range

Fix

🐘Packagist

`openmage/magento-lts` 

all versions

20.17.0`composer require openmage/magento-lts:^20.17.0`

## Affected Products

1 product · 1 configurations

Application

`magento`openmage

< 20.17.0

range

## Detection & mitigation playbook

Open-source dependency

1.  ### Detect
    
    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for openmage/magento-lts, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
    
2.  ### Fix
    
    Update openmage/magento-lts to 20.17.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-40098 is resolved across your whole dependency graph.
    
3.  ### Workarounds
    
    Put an independent control in front of the weakness: restrict the affected endpoint or interface to trusted networks, require an additional authentication factor or proxy-level check, and invalidate existing sessions and credentials in case the flaw has already been used.
    

## Frequently Asked Questions

\# Cross-user wishlist item import via shared wishlist code, leading to private option disclosure and file-disclosure variant ## Summary The shared wishlist add-to-cart endpoint authorizes access with a public \`sharing\_code\`, but loads the acted-on wishlist item by a separate global \`wishlist\_item\_id\` and never verifies that the item belongs to the shared wishlist referenced by that code. This lets an attacker use: - a valid shared wishlist code for wishlist A - a wishlist item ID belonging to victim wishlist B to import victim item B into the attacker's cart through the shared wishlist fl

O3 Security · Impact-Aware SCA

### Is CVE-2026-40098 in your dependencies?

Find it across Packagist, including transitive dependencies.

[Scan my dependencies](/book-demo) [How O3 SCA works](/impact-aware-sca)