Skip to content

Stored XSS in model description + workflow bypass lets any logged-in user publish malicious marketplace listings #278

@sonw-vh

Description

@sonw-vh

Describe the bug
A seller can publish (“commercialize”) a model to the public marketplace with a malicious HTML payload in model_desc and with essentially empty/invalid metadata. A server-side moderation/cleanup step appears to try deleting or clearing tasks after creation, but this can be bypassed by dropping the DELETE request and then posting tasks back.

Impact: The result is stored cross-site scripting (XSS) available to all visitors, which can be abused for session hijacking, credential theft, account takeover and large-scale phishing.

CVSS v3.1: 8.7 (High) - Vector: AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N

To Reproduce: (Use Burp Suite or any man-in-the-middle proxy tool)
Prerequisite: If you are using Burp Suite, learn this technique to catch the http response. Turn Intercept on all the time, right-click to the observed http request and choose `Do intercept > Response to this request".

Image
  1. Go to https://app.aixblock.io/models-seller/add and fill in random content.
Image
  1. Submit a model via POST /api/model_marketplace/commercialize-model (multipart/form-data) with minimal fields and a malicious description, e.g. model_desc=<svg onload=alert('XSS')>; leave many fields empty (docker_image, docker_access_token, model_token, etc.).
    • Example success response: HTTP/2 200 with {"messages":"Commercialize Model Successfully","id":857} and the model status becomes created → visible later as in_marketplace.
Image
  1. Intercept the follow-up DELETE /api/model_marketplace_tasks/{id} (which appears intended to remove/sanitize the listing) and drop it.
    • In the observed flow, a DELETE /api/model_marketplace_tasks/857 with body {"task_ids":[]} returned 200 but was ineffective.
Image
  1. Immediately send POST /api/model_marketplace_tasks/{id} with a valid task id (e.g., {"task_ids":[2]}) to “add” tasks back.
    • Example success response: HTTP/2 200 with {"detail":"Tasks added successfully"}.
Image
  1. Verify with GET /api/model_marketplace/list-sell?page=1&page_size=12.
    • The created items (e.g., ids 857) are returned with status:"in_marketplace", model_source:"HUGGING_FACE", and model_desc containing the injected markup (e.g., encoded <script> or raw SVG depending on view).
Image
  1. Open the model page (e.g., GET /marketplace/models/857). The model remains listed despite the malicious description and missing/invalid required fields.
Image

Expected behavior

  • Server should reject or quarantine submissions that contain HTML/JS in model_desc (e.g., strip to a safe allowlist or store as plain text) and block SVG/script execution in all render contexts.
  • Commercialization should validate business rules (required fields present, trusted sources/tokens, allowed tasks, etc.) before setting status to a publicly visible state.
  • Post-creation automation should be atomic and enforced server-side; a client dropping a moderation/cleanup DELETE must not allow the listing to remain public.
  • DELETE /api/model_marketplace_tasks/{id} with an empty payload should not succeed or should deterministically revert the model to a non-public state.

Desktop (please complete the following information):

  • OS: Windows 10 (reported by User-Agent)
  • Browser: Chrome 140
  • Version: 140.0.0.0

Smartphone (please complete the following information):

  • Device: N/A
  • OS: N/A
  • Browser: N/A
  • Version: N/A

Technical Details:

  • Vulnerable Components:

    • frontend/src/components/ModelMarketplace/ModelDetail/Index.tsx:881
    • frontend/src/pages/Project/Settings/ML/ModelDetail/Index.tsx:691
    • frontend/src/pages/Project/Settings/ML/ModelMarketPlace/ModelItem/Index.tsx:35
  • Vulnerable Code Pattern:

    <div dangerouslySetInnerHTML={{ __html: item?.model_desc }} />

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions