Every CVE Search/ Get API key

CVE-2026-113787

odf-kit: HTML injection leading to XSS in odtToHtml() via unescaped style attribute values

6.1 MediumFix available

odf-kit allows users to generate, fill, read, and convert OpenDocument Format files (.odt, .ods) in TypeScript and JavaScript. Starting in version 0.6.0 and prior to version 0.14.2, he renderer has an escapeHtml() helper and applies it consistently to text content and to attribute values — href, src, alt, id, data-author, data-date, citation text all go through it. The inline CSS strings do not. In renderTextSpan (dist/odt/to-html/html-renderer.js:195), the value of e.g. fo:color is copied from the document into style.fontColor verbatim by the parser (extractSpanStyle, read/parser.js:348), then concatenated raw into the attribute. A " in the value terminates the attribute early. The same unescaped style="${...}" pattern appears at roughly ten other emission sites: paragraph and heading (paragraphStyleToCss), table cells and rows (cellStyleToCss, rowStyleToCss), <col>, and the image style attribute. The affected source attributes include fo:color, fo:background-color, fo:text-shadow, fo:letter-spacing, fo:font-family (via both direct and font-face resolution), fo:margin-*, fo:padding-*, fo:line-height, fo:border*, and style:vertical-align. Version 0.14.2 contains a patch.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
Required

What an attacker can affect

Confidentiality
Low
Integrity
Low
Availability
None

Exploit likelihood

0.25%Unchanged since Oct 22, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.1

odf-kit: HTML injection leading to XSS in odtToHtml() via unescaped style attribute values

odf-kit allows users to generate, fill, read, and convert OpenDocument Format files (.odt, .ods) in TypeScript and JavaScript. Starting in version 0.6.0 and prior to version 0.14.2, he renderer has an escapeHtml() helper and applies it consistently to text content and to attribute values — href, src, alt, id, data-author, data-date, citation text all go through it. The inline CSS strings do not. In renderTextSpan (dist/odt/to-html/html-renderer.js:195), the value of e.g. fo:color is copied from the document into style.fontColor verbatim by the parser (extractSpanStyle, read/parser.js:348), then concatenated raw into the attribute. A " in the value terminates the attribute early. The same unescaped style="${...}" pattern appears at roughly ten other emission sites: paragraph and heading (paragraphStyleToCss), table cells and rows (cellStyleToCss, rowStyleToCss), <col>, and the image style attribute. The affected source attributes include fo:color, fo:background-color, fo:text-shadow, fo:letter-spacing, fo:font-family (via both direct and font-face resolution), fo:margin-*, fo:padding-*, fo:line-height, fo:border*, and style:vertical-align. Version 0.14.2 contains a patch.

Record
CVE-2026-113787
CVSS 3.1
6.1 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
EUVDEUVD-2026-107324 6.1

odf-kit: HTML injection leading to XSS in odtToHtml() and odsToHtml() via unescaped style attribute values

Record
EUVD-2026-107324
CVSS 3.1
6.1 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Updated
2026-11-04
GitHub AdvisoriesGHSA-3cgg-c5pp-57h6 6.1

odf-kit: HTML injection leading to XSS in odtToHtml() and odsToHtml() via unescaped style attribute values

Summary

ODF style attribute values are interpolated into style="..." attributes without HTML-escaping in both of odf-kit's to-HTML renderers (odtToHtml and odsToHtml). A double-quote character inside an attacker-controlled style value breaks out of the attribute, allowing arbitrary HTML/attribute injection — and therefore script execution (XSS) — from a crafted .odt or .ods file wherever the rendered output is inserted as HTML, which is the documented purpose of both functions.

Details

ODT renderer (src/odt/to-html/html-renderer.ts)

The renderer has an escapeHtml() helper and applies it consistently to text content and to attribute values — href, src, alt, id, data-author, data-date, citation text all go through it. The inline CSS strings do not.

In renderTextSpan (dist/odt/to-html/html-renderer.js:195):

const css = spanStyleToCss(span.style);
if (css)
    html = `<span style="${css}">${html}</span>`;

The value of e.g. fo:color is copied from the document into style.fontColor verbatim by the parser (extractSpanStyle, read/parser.js:348), then concatenated raw into the attribute. A " in the value terminates the attribute early.

The same unescaped style="${...}" pattern appears at roughly ten other emission sites: paragraph and heading (paragraphStyleToCss), table cells and rows (cellStyleToCss, rowStyleToCss), <col>, and the image style attribute. The affected source attributes include fo:color, fo:background-color, fo:text-shadow, fo:letter-spacing, fo:font-family (via both direct and font-face resolution), fo:margin-*, fo:padding-*, fo:line-height, fo:border*, and style:vertical-align.

ODS renderer (src/ods/to-html/html-renderer.ts) — same bug

buildInlineStyle() assembles the CSS string from cell formatting properties — fo:color, fo:font-size, fo:font-family, fo:background-color, fo:text-align, etc. — with zero escapeHtml calls, and renderCell emits it raw (line 65):

if (includeStyles && cell.formatting) {
    const style = buildInlineStyle(cell.formatting);
    if (style) attrs.push(`style="${style}"`);
}

Additionally, row.height (from style:row-height) goes raw into the row element (line 95):

const style = includeStyles && row.height ? ` style="height:${row.height}"` : "";
return `<tr class="${prefix}-row"${style}>${cells}</tr>`;

The same injection is reachable through the public odf-kit/ods/to-html export (odsToHtml()), so both to-HTML directions are affected.

Version scope

The odt/to-html and ods/to-html modules first shipped in 0.14.0; the current latest release is 0.14.1. The PoCs were re-ran against the unreleased main branch (commit 270a361) — both injections still fire, so no fix has landed past the release.

PoC

Each PoC is a minimal ODF package (mimetype + META-INF/manifest.xml + content.xml) whose content.xml contains exactly one poisoned automatic style. The files are generated by this short Python script (stdlib only, no dependencies) — save as build-pocs.py and run python3 build-pocs.py:

import zipfile

def build(path, mimetype, content):
    # ODF requires 'mimetype' first and stored uncompressed
    with zipfile.ZipFile(path, "w") as z:
        z.writestr(zipfile.ZipInfo("mimetype"), mimetype, compress_type=zipfile.ZIP_STORED)
        z.writestr("META-INF/manifest.xml",
            '<?xml version="1.0" encoding="UTF-8"?>\n'
            '<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n'
            ' <manifest:file-entry manifest:full-path="/" manifest:media-type="' + mimetype + '"/>\n'
            ' <manifest:file-entry manifest:full-path="content.xml" manifest:media-type="text/xml"/>\n'
            '</manifest:manifest>\n')
        z.writestr("content.xml", content)

ODT = "application/vnd.oasis.opendocument.text"
ODS =…
Record
GHSA-3cgg-c5pp-57h6
CVSS 3.1
6.1 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-04
NVD 6.1

odf-kit allows users to generate, fill, read, and convert OpenDocument Format files (.odt, .ods) in TypeScript and JavaScript. Starting in version 0.6.0 and prior to version 0.14.2, he renderer has an escapeHtml() helper and applies it consistently to text content and to attribute values — href, src, alt, id, data-author, data-date, citation text all go through it. The inline CSS strings do not. In renderTextSpan (dist/odt/to-html/html-renderer.js:195), the value of e.g. fo:color is copied from the document into style.fontColor verbatim by the parser (extractSpanStyle, read/parser.js:348), then concatenated raw into the attribute. A " in the value terminates the attribute early. The same unescaped style="${...}" pattern appears at roughly ten other emission sites: paragraph and heading (paragraphStyleToCss), table cells and rows (cellStyleToCss, rowStyleToCss), <col>, and the image style attribute. The affected source attributes include fo:color, fo:background-color, fo:text-shadow, fo:letter-spacing, fo:font-family (via both direct and font-face resolution), fo:margin-*, fo:padding-*, fo:line-height, fo:border*, and style:vertical-align. Version 0.14.2 contains a patch.

Record
CVE-2026-113787
CVSS 3.1
6.1 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
OSV 6.1

odf-kit: HTML injection leading to XSS in odtToHtml() via unescaped style attribute values

odf-kit allows users to generate, fill, read, and convert OpenDocument Format files (.odt, .ods) in TypeScript and JavaScript. Starting in version 0.6.0 and prior to version 0.14.2, he renderer has an escapeHtml() helper and applies it consistently to text content and to attribute values — href, src, alt, id, data-author, data-date, citation text all go through it. The inline CSS strings do not. In renderTextSpan (dist/odt/to-html/html-renderer.js:195), the value of e.g. fo:color is copied from the document into style.fontColor verbatim by the parser (extractSpanStyle, read/parser.js:348), then concatenated raw into the attribute. A " in the value terminates the attribute early. The same unescaped style="${...}" pattern appears at roughly ten other emission sites: paragraph and heading (paragraphStyleToCss), table cells and rows (cellStyleToCss, rowStyleToCss), <col>, and the image style attribute. The affected source attributes include fo:color, fo:background-color, fo:text-shadow, fo:letter-spacing, fo:font-family (via both direct and font-face resolution), fo:margin-*, fo:padding-*, fo:line-height, fo:border*, and style:vertical-align. Version 0.14.2 contains a patch.

Record
CVE-2026-113787
CVSS 3.1
6.1 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
OSVGHSA-3cgg-c5pp-57h6 6.1

odf-kit: HTML injection leading to XSS in odtToHtml() and odsToHtml() via unescaped style attribute values

Summary

ODF style attribute values are interpolated into style="..." attributes without HTML-escaping in both of odf-kit's to-HTML renderers (odtToHtml and odsToHtml). A double-quote character inside an attacker-controlled style value breaks out of the attribute, allowing arbitrary HTML/attribute injection — and therefore script execution (XSS) — from a crafted .odt or .ods file wherever the rendered output is inserted as HTML, which is the documented purpose of both functions.

Details

ODT renderer (src/odt/to-html/html-renderer.ts)

The renderer has an escapeHtml() helper and applies it consistently to text content and to attribute values — href, src, alt, id, data-author, data-date, citation text all go through it. The inline CSS strings do not.

In renderTextSpan (dist/odt/to-html/html-renderer.js:195):

const css = spanStyleToCss(span.style);
if (css)
    html = `<span style="${css}">${html}</span>`;

The value of e.g. fo:color is copied from the document into style.fontColor verbatim by the parser (extractSpanStyle, read/parser.js:348), then concatenated raw into the attribute. A " in the value terminates the attribute early.

The same unescaped style="${...}" pattern appears at roughly ten other emission sites: paragraph and heading (paragraphStyleToCss), table cells and rows (cellStyleToCss, rowStyleToCss), <col>, and the image style attribute. The affected source attributes include fo:color, fo:background-color, fo:text-shadow, fo:letter-spacing, fo:font-family (via both direct and font-face resolution), fo:margin-*, fo:padding-*, fo:line-height, fo:border*, and style:vertical-align.

ODS renderer (src/ods/to-html/html-renderer.ts) — same bug

buildInlineStyle() assembles the CSS string from cell formatting properties — fo:color, fo:font-size, fo:font-family, fo:background-color, fo:text-align, etc. — with zero escapeHtml calls, and renderCell emits it raw (line 65):

if (includeStyles && cell.formatting) {
    const style = buildInlineStyle(cell.formatting);
    if (style) attrs.push(`style="${style}"`);
}

Additionally, row.height (from style:row-height) goes raw into the row element (line 95):

const style = includeStyles && row.height ? ` style="height:${row.height}"` : "";
return `<tr class="${prefix}-row"${style}>${cells}</tr>`;

The same injection is reachable through the public odf-kit/ods/to-html export (odsToHtml()), so both to-HTML directions are affected.

Version scope

The odt/to-html and ods/to-html modules first shipped in 0.14.0; the current latest release is 0.14.1. The PoCs were re-ran against the unreleased main branch (commit 270a361) — both injections still fire, so no fix has landed past the release.

PoC

Each PoC is a minimal ODF package (mimetype + META-INF/manifest.xml + content.xml) whose content.xml contains exactly one poisoned automatic style. The files are generated by this short Python script (stdlib only, no dependencies) — save as build-pocs.py and run python3 build-pocs.py:

import zipfile

def build(path, mimetype, content):
    # ODF requires 'mimetype' first and stored uncompressed
    with zipfile.ZipFile(path, "w") as z:
        z.writestr(zipfile.ZipInfo("mimetype"), mimetype, compress_type=zipfile.ZIP_STORED)
        z.writestr("META-INF/manifest.xml",
            '<?xml version="1.0" encoding="UTF-8"?>\n'
            '<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n'
            ' <manifest:file-entry manifest:full-path="/" manifest:media-type="' + mimetype + '"/>\n'
            ' <manifest:file-entry manifest:full-path="content.xml" manifest:media-type="text/xml"/>\n'
            '</manifest:manifest>\n')
        z.writestr("content.xml", content)

ODT = "application/vnd.oasis.opendocument.text"
ODS =…
Record
GHSA-3cgg-c5pp-57h6
CVSS 3.1
6.1 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-04

Affected products

Affected packages

Affected packages
PackageAffectedFixed
odf-kit
npm
0.6.0 up to 0.14.2
0.14.2

History

History
RecordedChangedSources
publishedEUVD
affected, referencesOSV
affected, facts, referencesGitHub Advisories
first indexedCVE List, EUVD, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-113787 is a medium vulnerability (CVSS 6.1) in Githubnewbie0 Odf-kit, published October 21, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.25%, the 16th percentile. Fixed in odf-kit 0.14.2.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open