Stored XSS and CSP Bypass in KiwiTCMS in kiwitcms/kiwi


Reported on

Apr 29th 2023


Stored XSS, also known as persistent XSS, is the more damaging of the XSS. It occurs when a malicious script is injected directly into a vulnerable web application. Due to a sanitization problem it is possible to perform a Stored XSS. The problem is that the upload function permit malicious extensions like svg file. Due to this stored xss it is possible to become admin and perform other malicious actions using api endpoint.

The attack is easily executable by initially bypassing the regex that prevents script uploads, and finally the Content Security Policy.

Step to Reproduce:

1 - The Content Security Policy is script-src 'self' , so the first step will be to upload a "test.js" file via file upload, for example a simple alert(). 2 - Some security and regex checks are implemented to prevent material containing "scripts" from being uploaded. To bypass the regex checks, it is possible, for example, to upload an HTML file and use the tag <ScRipt, with some letters in uppercase. Any inline script will be blocked, but having previously created a "test.js" file containing some code, we can call that and it will run. A possible payload can be:

<Script src='/uploads/tenant/public/attachments/testplans_testplan/7002/test.js'></Script>

Now when an admin or other users will open the link, the XSS will be triggered.

POC Video:


Stored XSS to run malicious javascript. Possibility to become admin and use also other api endpoint without permission.

We are processing your report and will contact the kiwitcms/kiwi team within 24 hours. a month ago
We have contacted a member of the kiwitcms/kiwi team and are waiting to hear back 25 days ago
kiwitcms/kiwi maintainer modified the Severity from Critical (9.1) to High (8.1) 5 days ago
The researcher has received a minor penalty to their credibility for miscalculating the severity: -1
Alexander Todorov validated this vulnerability 5 days ago

I recommend trying to integrate Dompurify

From what we can tell Dompurify is a Node.js library while Kiwi TCMS is implemented in Python. The two aren't compatible and spinning up a Node.js process on every file upload is very heavy operation so for now that's a no-go solution.

We've improved the existing validator code and also will force all uploaded files to be served as text/plain to prevent the browser from interpreting them.

(It could be a good idea to remove any malicious codes) and to create a less permissive CSP.

If you have a specific example please open a PR and disclose it responsibly so that we can examine it.

Antonio Spataro has been awarded the disclosure bounty
The fix bounty is now up for grabs
The researcher's credibility has increased: +7
Alexander Todorov marked this as fixed in 12.3 with commit afc320 5 days ago
The fix bounty has been dropped
This vulnerability will not receive a CVE
This vulnerability is scheduled to go public on May 29th 2023
Antonio Spataro
5 days ago


hey @atodorov, is it possible to get a CVE for this vulnerability too? I would be very pleased, thank you very much for your availability. if during my free time I find an example I can open a PR without problems, I'm a bit busy with work but if possible I'll lend a hand

Alexander Todorov published this vulnerability 4 days ago
3 days ago


Geez, I don't know how many times I have to comment on this disclosure so that the comment makes it through. 3rd time is the charm!

CVE number for this vulnerability will be assigned by GitHub, see

to join this conversation