FlawOpen

flawopen.com/Teardowns/cve-2026-63277-libreoffice-calc-jdbc-classpath-rce

● CVE-2026-63277 · CVSS v4 8.5 · High
FlawOpen Security Research

CVE-2026-63277: LibreOffice Calc spreadsheet RCE

A crafted Calc document could use an external data mapping to make LibreOffice resolve a Java database-driver class from a non-local class-path URL when a person opened it. LibreOffice 26.2.5 and 26.8.0 restrict these entries to the file scheme; this is a document-open interaction, not a zero-click network flaw.[1], [2], [3]

💡 Plain English Explainer (ELI5)

A spreadsheet can carry a note telling the office program where to look for a database driver. Before the fix, that note could point to a web address and the program could load Java code from it when someone opened the sheet. The fix accepts only addresses labeled file:. That narrows the route, though the label alone is not a guarantee that every target is physically local.[1], [4], [5]

Core Concepts & Subsystem Terms

External data mapping
A Calc document setting that describes how the sheet connects to an external data source.[1]
JDBC driver
Java software that lets an application communicate with a database.[1]
Class path
A set of locations from which Java can load classes and related resources.[4], [5]
CWE-829
Inclusion of functionality from an untrusted control sphere; here, the affected path accepted a class-path URL outside the intended local-file scheme.[6], [1]

Framework mappings

  • CWE reference for the weakness described in this guide: CWE-829

Root Cause Analysis

The vulnerable jvmaccess::ClassPath::translateToUrls path expanded each Java class-path entry and passed it to Java's URL constructor without first restricting its scheme. The 26.2.5.2 source adds URI parsing and rejects entries whose scheme is not file before constructing the Java URL. The advisory ties the path to Calc external data mappings and JDBC driver loading. Exploitation requires a person to open a crafted document; the sources cited here do not establish zero-click reachability or exploitation in the wild. The guard is specifically a scheme check: do not describe it as a general authorization policy or claim it rejects every remote file share.[1], [4], [5]

CVE-2026-63277: document and version reachability

SituationWhat the evidence establishesAction
A Calc file contains an external data mapping that names a Java database driver at a remote class-path URL, and a person opens the file.The TDF advisory says the document-open path can run Java code from that location. This requires a crafted document and user interaction; it is not evidence of a zero-click attack or exploitation in the wild.Treat untrusted Calc attachments as risky and update LibreOffice; do not rely on macro prompts to block this Java loading path.
LibreOffice 26.2 series earlier than 26.2.5.The CVE record identifies this 26.2 range as affected. TDF lists 26.2.5 and 26.8.0 as fixed releases; the record does not establish status for every earlier or downstream build.Verify the installed upstream or distribution package and backport status; install a vendor-fixed package.
A patched release accepts a file: class-path entry.The source guard checks the URI scheme. It does not prove that every file: target is physically local or that all network-share forms are rejected.Do not interpret the file: scheme check as a complete filesystem authorization boundary; retain appropriate OS and application controls.

Step-by-Step Attack Flow

Step 1

A document carries an external data mapping

The affected document describes an external source and a Java database driver class path.[1], [4]

Step 2

A person opens the document

User interaction is required; opening an arbitrary spreadsheet is not equivalent to a remotely triggered, zero-click exploit.[1], [2]

Step 3

The Java class path is translated

Before the fix, translateToUrls passed an expanded entry to Java's URL constructor without checking whether its scheme was local-file.[4]

Step 4

The referenced driver can be loaded

The vendor advisory describes the resulting Java loading path. Impact depends on the document, configuration, and Java integration; do not infer that every Calc document or installation is exploitable.[1], [2]

Step 5

The fixed code rejects non-file schemes

LibreOffice 26.2.5.2 parses the URI and throws before URL construction unless its scheme is file. Install a fixed vendor or distribution build.[5], [1]

Source Code: Flaw vs. Secure Implementation

These focused excerpts are copied from the version-pinned upstream translateToUrls implementation. The 26.2.4.2 path expands the entry and proceeds directly to Java URL construction. The 26.2.5.2 path inserts URI parsing and rejects entries whose scheme is not file before that construction. The source diff establishes the scheme-validation boundary; the vendor advisory establishes the Calc/JDBC document path. This is source analysis, not a runnable proof of concept.[4], [5], [1]

Source excerpt: jvmaccess/source/classpath.cxx — translateToUrls

UNPATCHED FLAW
// LibreOffice 26.2.4.2 — jvmaccess/source/classpath.cxx
if (!url.isEmpty()) {
    css::uno::Reference< css::uri::XVndSunStarExpandUrlReference >
        expUrl(
            css::uri::UriReferenceFactory::create(context)->parse(url),
            css::uno::UNO_QUERY);
    if (expUrl.is()) {
        css::uno::Reference< css::util::XMacroExpander > expander =
            css::util::theMacroExpander::get(context);
        try {
            url = expUrl->expand( expander );
        } catch (const css::lang::IllegalArgumentException & e) {
            css::uno::Any anyEx = cppu::getCaughtException();
            throw css::lang::WrappedTargetRuntimeException(
                "com.sun.star.lang.IllegalArgumentException: "
                 + e.Message,
                 nullptr, anyEx );
        }
    }
    jvalue arg;
    arg.l = environment->NewString(
        reinterpret_cast< jchar const * >(url.getStr()),
        static_cast< jsize >(url.getLength()));
    if (arg.l == nullptr) {
        return nullptr;
    }
    jobject o(environment->NewObjectA(classUrl, ctorUrl, &arg));
    if (o == nullptr) {
        return nullptr;
    }
    urls.push_back(o);
}
HARDENED SECURE PATCH
// LibreOffice 26.2.5.2 — jvmaccess/source/classpath.cxx
if (!url.isEmpty()) {
    css::uno::Reference< css::uri::XVndSunStarExpandUrlReference >
        expUrl(
            css::uri::UriReferenceFactory::create(context)->parse(url),
            css::uno::UNO_QUERY);
    if (expUrl.is()) {
        css::uno::Reference< css::util::XMacroExpander > expander =
            css::util::theMacroExpander::get(context);
        try {
            url = expUrl->expand( expander );
        } catch (const css::lang::IllegalArgumentException & e) {
            css::uno::Any anyEx = cppu::getCaughtException();
            throw css::lang::WrappedTargetRuntimeException(
                "com.sun.star.lang.IllegalArgumentException: "
                 + e.Message,
                 nullptr, anyEx );
        }
    }
    css::uno::Reference< css::uri::XUriReference > uriRef(
        css::uri::UriReferenceFactory::create(context)->parse(url));
    if (!uriRef.is() || !uriRef->getScheme().equalsIgnoreAsciiCase("file"))
    {
        throw css::lang::IllegalArgumentException(
            "non-local Java class path entry: " + url,
            css::uno::Reference< css::uno::XInterface >(), 0);
    }
    jvalue arg;
    arg.l = environment->NewString(
        reinterpret_cast< jchar const * >(url.getStr()),
        static_cast< jsize >(url.getLength()));
    if (arg.l == nullptr) {
        return nullptr;
    }
    jobject o(environment->NewObjectA(classUrl, ctorUrl, &arg));
    if (o == nullptr) {
        return nullptr;
    }
    urls.push_back(o);
}

Engineering & System Hardening Checklist

Sources