Files
infocom-systems-design/node_modules/@zenuml/core/docs/xss.md
2025-10-03 22:27:28 +03:00

2.6 KiB

In this document we are disclosing a cross-site scripting vulnerability in the @zenuml/core package. XSS is a type of security vulnerability that allows an attacker to inject malicious code into a web page viewed by other users.

How to reproduce

ZenUML generates sequence diagrams from text. If the text contains a malicious script, it will be executed when the diagram is rendered.

The following content is known to pop an alert box:

"><img src=x onerror=alert(1)>ent #FFEBE6

Known affected products

Product Severity Comment
Confluence plugin P3 Content must be create by registered users; scripts run in sandbox.
Web App P3 Only the current user can view content created by themselves.
Chrome Extension P3 Only the current user can view content created by themselves.
Desktop (Win/Mac) P3 Only the current user can view content created by themselves.
JetBrains plugin P3 Scripts run inside sandbox.

What is the cause of the vulnerability?

The cause of the XSS vulnerability in @zenuml/core is due to accepting an arbitrary text as innerHTML in the WidthProviderFunc.ts file. Specifically, the vulnerability is located in the code that measures the width of the message or participant element in the library. The issue is present in line 29 of the file, which can be found at this URL. In this line, the code uses unsanitized user input which is passed as an argument in the function, this allows an attacker to inject malicious JavaScript code into the web page viewed potentially by other users.

  let hiddenDiv = document.querySelector('.textarea-hidden-div') as HTMLDivElement;
  if (!hiddenDiv) {
    const newDiv = document.createElement('div');
    ...
    document.body.appendChild(newDiv);
    hiddenDiv = newDiv;
  }
  hiddenDiv.innerHTML = text;
  const scrollWidth = hiddenDiv.scrollWidth;
  return scrollWidth;

Fix of the vulnerability

The fix is to replace the innerHTML with textContent in the code. This will prevent the browser from interpreting the text as HTML and will treat it as plain text.

  ...
  hiddenDiv.textContent = text;
  const scrollWidth = hiddenDiv.scrollWidth;
  return scrollWidth;