CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-9318

CVE-2026-9318: Stored Cross-Site Scripting via HTML Export in Jazzband tablib

Amit Schendel
Amit Schendel
Senior Security Researcher

Aug 12, 2026·8 min read·4 visits

Executive Summary (TL;DR)

A stored XSS vulnerability in Jazzband tablib prior to 3.10.0 allows remote attackers to execute arbitrary JavaScript in browsers via crafted spreadsheet sheet names processed through HTML export pipelines.

CVE-2026-9318 is a stored cross-site scripting (XSS) vulnerability affecting Jazzband tablib versions prior to 3.10.0. The flaw is located in the HTML export functionality of multi-sheet Databook objects. Due to raw f-string interpolation, unsanitized sheet titles containing malicious script tags are rendered directly as HTML, allowing arbitrary client-side code execution in a victim's browser.

Vulnerability Overview

The library tablib is a format-agnostic tabular dataset manager in Python, maintained under the Jazzband organization. It is utilized to import, manipulate, and export data in multiple formats including XLSX, ODS, JSON, YAML, and HTML. Because applications rely on tablib to parse user-uploaded spreadsheets and convert them into other configurations, it exposes an entry point for processing untrusted structural metadata.

The stored cross-site scripting vulnerability, identified as CVE-2026-9318, occurs inside the HTML export pipeline for multi-sheet datasets, represented by Databook objects. When exporting a Databook to HTML, the library does not sanitize user-controlled worksheet names. If an attacker delivers a worksheet containing a script sequence in its metadata, the library parses and interpolates it directly into the generated output stream.

In typical production environments, the generated HTML page is subsequently rendered within a web application's administration console or reporting interface. This design flaw crosses a trust boundary, because worksheet metadata is assumed to contain only plain text layout labels. When a browser loads the exported document, it processes the script element under the hosting domain's security context.

This flaw is classified under CWE-79 (Improper Neutralization of Input During Web Page Generation). It presents a significant stored XSS risk because the spreadsheet does not execute payload strings on the backend, but stores the payload in a passive state until the HTML representation is triggered. Downstream integrations like django-import-export are also exposed to these data injection vectors if they permit spreadsheet upload and render sheet exports dynamically.

Root Cause Analysis

The architectural root cause of CVE-2026-9318 resides in the export_book method within the format handler module src/tablib/formats/_html.py. The class utilizes raw string concatenation and Python f-string formatting when constructing headings for individual worksheets. This pattern operates on the unsafe assumption that titles of sheets are sanitized before being assigned to Dataset objects.

During processing, the program executes a loop iterating over each dataset in the databook. The library assigns the value of dset.title to a local variable named title. If no sheet name exists, it assigns a default string representation. The flaw is exposed when the title is compiled into the document output stream: result += f'<{cls.BOOK_ENDINGS}>{title}</{cls.BOOK_ENDINGS}>\n'.

The default value of cls.BOOK_ENDINGS is the HTML tag 'h3'. Since the interpolation uses raw formatting rather than an HTML-safe encoder, any character sequence representing tags, such as <script>, is injected directly into the HTML payload as an operational tag rather than plain text. This directly leads to structural HTML injection.

Furthermore, spreadsheet parsers such as openpyxl or odfpyxl extract tab names straight from compressed XML structures inside modern office files. Because these parsers do not block special HTML characters in worksheet titles, the malicious elements flow into tablib without any validation boundaries. The absence of output sanitization at the terminal step is the core vulnerability.

Code Analysis

To understand the vulnerable code path, observe the implementation of export_book in tablib versions preceding 3.10.0:

# Vulnerable version of export_book in src/tablib/formats/_html.py
def export_book(cls, databook):
    result = ''
    for i, dset in enumerate(databook._datasets):
        title = dset.title if dset.title else f'Set {i}'
        # Unsanitized concatenation of dset.title into output buffer
        result += f'<{cls.BOOK_ENDINGS}>{title}</{cls.BOOK_ENDINGS}>\n'
        result += dset.html
        result += '\n'

The implementation does not perform any escaping operations on title prior to evaluating the formatted string. To remediate this issue, the patch submitted in PR #668 implements safe node instantiation and serialization using Python's xml.etree.ElementTree module:

# Patched version of export_book in src/tablib/formats/_html.py
import xml.etree.ElementTree as ET
 
def export_book(cls, databook):
    result = ''
    for i, dset in enumerate(databook._datasets):
        title = dset.title if dset.title else f'Set {i}'
        # Safe generation using xml.etree.ElementTree
        title_el = ET.Element(cls.BOOK_ENDINGS)
        title_el.text = title
        result += ET.tostring(title_el, method='html', encoding='unicode') + '\n'
        result += dset.html
        result += '\n'

By leveraging ET.Element, the developer configures the DOM element using programmatic parameters where title is isolated strictly inside the .text property of the node. When ET.tostring is executed with the html serialization parameter, the standard library automatically encodes HTML-sensitive metacharacters. Characters such as < and > are translated to &lt; and &gt; respectively, which guarantees they are interpreted by the browser engine as plain text content rather than markup.

Analyzing the fix reveals that it successfully neutralizes the target injection channel without degrading performance or functionality. However, developers must ensure that elements surrounding dset.html do not introduce secondary cross-site scripting vulnerabilities elsewhere in the dataset body parsing pipeline.

Exploitation Methodology

Exploitation of CVE-2026-9318 requires two primary phases: an upload of a malicious spreadsheet file, and the execution of an HTML export that renders in an administrative or user context. The initial access vector is low-complexity and requires only standard file-upload privileges, which are commonly granted to end-users of business intelligence portals.

An attacker begins by preparing an ODS or XLSX spreadsheet document. Using standard programmatic tools or directly modifying the document's underlying XML, the attacker renames a sheet tab to include a client-side execution sequence. For example, setting the sheet name to <script>fetch("https://github.com/jazzband/tablib")</script> sets up the execution phase.

When the document is uploaded, the target application uses tablib to parse the workbook and populate a Databook object. The malicious sheet name is mapped directly into dset.title as a standard string. Once the administrative dashboard triggers an HTML render event, the code runs, producing a payload output that the browser compiles and executes.

Below is the sequence of events illustrating this attack lifecycle:

Prerequisites for a successful exploit include an active target rendering the HTML results without secondary escaping mechanisms. Many standard implementations display the raw HTML using template directives such as Django's |safe filter or Jinja2's |safe rendering. This bypasses the framework's native protection mechanisms, resulting in stored cross-site scripting.

Impact Assessment

The impact of this vulnerability depends on the privilege level of the victim user who views the HTML export. Because HTML pages generated by tablib are often administrative or audit reports, the typical victim is likely a privileged user or system administrator. Consequently, exploitation has a high probability of targeting management sessions.

When the payload executes in the victim's browser, it operates within the context of their authenticated session. If the application does not utilize secure cookie configurations, the script can extract session identifiers or authorization headers from document.cookie or LocalStorage. This allows the attacker to hijack active sessions and assume the victim's identity.

Beyond simple credential harvesting, the script can execute complex administrative actions. This includes initiating unauthorized API requests, modifying account configurations, or creating new administrative profiles within the target system. The scope of impact is classified as 'Changed' (S:C) because the browser sandbox exploitation breaks out of the context of the underlying library and affects the parent web application environment.

While CVSS assigns a medium score of 5.4, the relative danger is higher in enterprise environments where spreadsheet parsing is heavily automated. If the server application integrates other components with the compromised sheets, the integrity of downstream reporting workflows is broken.

Remediation and Detection

The most effective mitigation is upgrading to tablib version 3.10.0 or higher, which completely patches the vulnerable interpolation code. To upgrade the library in standard environments, execute the pip update command or modify your requirement configuration: pip install --upgrade tablib>=3.10.0.

If upgrading immediately is not feasible, implement input sanitization rules at the entry point of the ingestion pipeline. Define a strict whitelist regex for worksheet names, allowing only alphanumeric characters, underscores, hyphens, and spaces. Ensure any title failing this check is sanitized or rejected before the databook object is passed to export format routines.

Deploy a strict Content Security Policy (CSP) header on target application domains. The header Content-Security-Policy: default-src 'self'; script-src 'self' prevents inline execution of scripts, neutralizing payloads delivered via the sheet title. Additionally, set the HttpOnly attribute on session cookies to prevent retrieval by XSS scripts.

Perform regular security audits of template rendering paths. Ensure that exported HTML strings are not marked as safe within templating engines unless they have been explicitly run through an HTML sanitization engine. This prevents developer-level output configuration from re-introducing structural injection issues.

Official Patches

JazzbandOfficial patch containing the fix implementation using ElementTree serialization.

Fix Analysis (1)

Technical Appendix

CVSS Score
5.4/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
EPSS Probability
0.18%
Top 92% most exploited

Affected Systems

Jazzband tablib library (Python)

Affected Versions Detail

Product
Affected Versions
Fixed Version
tablib
Jazzband
< 3.10.03.10.0
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork (AV:N)
CVSS v3.1 Score5.4 (Medium)
EPSS Score0.00181
ImpactArbitrary client-side script execution (Stored XSS)
Exploit StatusProof of Concept (PoC) available
KEV StatusNot listed

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1185Browser Session Hijacking
Collection
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The software does not neutralize or incorrectly neutralizes user-controlled input before it is placed in output that is used as a web page that is served to other users.

Known Exploits & Detection

GitHub Pull Request #668The pull request includes integration test cases demonstrating the parsing of malicious sheet names triggering execution during the HTML export.

Vulnerability Timeline

Pull Request #668 submitted and merged into jazzband/tablib
2026-06-04
tablib version 3.10.0 released with the security patch
2026-08-12
Vulnerability publicly disclosed and CVE-2026-9318 assigned
2026-08-12

References & Sources

  • [1]Jazzband tablib Repository
  • [2]Pull Request #668: Escape book title for html format
  • [3]Fix Commit Patch file
  • [4]tablib 3.10.0 Release Notes
  • [5]VulnCheck Security Advisory
  • [6]NVD CVE-2026-9318 Details
  • [7]CVE.org Record

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 6 hours ago•CVE-2026-54917
10.0

CVE-2026-54917: Cross-Bucket Path Traversal and Authorization Bypass in SeaweedFS S3 and Iceberg Gateways

CVE-2026-54917 is a critical path traversal and authorization bypass vulnerability affecting the S3 and Iceberg REST catalog gateways in SeaweedFS. By explicitly disabling canonical path cleaning in the gorilla/mux routing system, relative path segments such as '..' are allowed to bypass routing constraints and access control checks. When these paths are collapsed server-side by the backend filer, they resolve to folders outside the authorized bucket boundary, allowing unauthorized cross-bucket access.

Amit Schendel
Amit Schendel
3 views•5 min read
•about 7 hours ago•GHSA-JWJP-4649-V8JP
7.5

GHSA-jwjp-4649-v8jp: Out-of-Bounds Read in SIPSorcery SCTP SACK Chunk Parsing

An out-of-bounds read vulnerability in the SCTP SACK chunk parser of SIPSorcery leads to Denial of Service (DoS) or silent internal state corruption due to lack of boundary validation on incoming chunk elements.

Amit Schendel
Amit Schendel
3 views•6 min read
•about 8 hours ago•GHSA-PFVM-W89X-94JW
7.5

GHSA-pfvm-w89x-94jw: Uncaught Exception in STUN Parser Causes Complete TurnServer Receive Loop Termination

An uncaught exception vulnerability exists in SIPSorcery's TurnServer component, where unauthenticated malformed UDP packets can crash the core UDP receive loop, resulting in a persistent Denial of Service.

Amit Schendel
Amit Schendel
7 views•6 min read
•1 day ago•CVE-2026-62898
7.5

CVE-2026-62898: Use After Free Information Disclosure in Microsoft QUIC

A critical use-after-free vulnerability in Microsoft QUIC allows unauthenticated remote attackers to disclose sensitive system memory over the network. The vulnerability is caused by a race condition during rapid connection termination and asynchronous packet retransmission.

Alon Barad
Alon Barad
12 views•6 min read
•1 day ago•CVE-2026-62899
5.9

CVE-2026-62899: .NET Security Feature Bypass Vulnerability (HTTP Request Smuggling)

CVE-2026-62899 is a security feature bypass vulnerability in the Microsoft .NET runtime environment on non-Windows platforms. The flaw manifests as an HTTP Request/Response Smuggling vulnerability (CWE-444) within the managed implementation of the System.Net.HttpListener class. This allows unauthenticated remote attackers to desynchronize request boundaries when the backend .NET application is hosted behind an upstream reverse proxy.

Amit Schendel
Amit Schendel
16 views•6 min read
•1 day ago•CVE-2026-62901
7.5

CVE-2026-62901: Remote Denial of Service via Infinite Loop in .NET WebSockets Engine

CVE-2026-62901 is a high-severity Denial of Service (DoS) vulnerability in the Microsoft .NET ecosystem, specifically affecting the System.Net.WebSockets frame-processing engine and associated network transports. Under certain circumstances, a remote, unauthenticated attacker can exploit this vulnerability by sending malformed or specifically crafted WebSocket packets over the network, causing a targeted .NET application server to enter a tight infinite loop. This behavior results in 100% CPU utilization on the executing thread, starving application resources and leading to a complete Denial of Service.

Alon Barad
Alon Barad
17 views•6 min read