# REPRO-2026-00377: LFI via calcext:data-mappings, sql provider and sdbc:flat file db href — document reads a local text file into the sheet ## Summary Status: published Severity: medium CVSS: Unknown CWE: CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor) Type: security Confidence: high ## Identifiers REPRO ID: REPRO-2026-00377 CVE: CVE-2026-63268 ## Package Name: LibreOffice/core Ecosystem: Maven Affected: LibreOffice versions before 26.2.5 / 26.8.0 that restore persisted data-provider links on document load; 26.2.4.2 confirmed as last vulnerable release Fixed: 26.2.5 ## Root Cause # CVE-2026-63268 — LFI via calcext:data-mappings, sql provider and sdbc:flat:file:// db href (LibreOffice Calc) ## Summary LibreOffice Calc persists external data-source links (`calcext:data-mappings`) inside ODS documents and restores them when the document is opened. In vulnerable versions the restoration is performed for *every* provider named in the document, including the unfinished `org.libreoffice.calc.sql` provider. On load, that provider parses the saved `calcext:id` as `table@database`, resolves the `database` component through `sdb::DatabaseContext` (which interprets an arbitrary unregistered name as a URL and loads it), connects to the resulting database and copies the result of `SELECT * FROM ` into a named database range of the sheet. Because an attacker can make that database resolve to an odb that names a **folder of local text files** as a `text/csv` file-based database — i.e. an `sdbc:flat:file://` connection URL handled by the flat Text/CSV SDBC driver, which exposes every text file in the folder as a table — merely opening the crafted ODS reads a local victim text file into the sheet (Local File Inclusion / information disclosure). ## Impact - Package/component affected: `sc` (LibreOffice Calc), external data mapping import/restore path: `sc/source/filter/xml/xmlmappingi.cxx` (`ScXMLMappingContext`), `sc/source/ui/dataprovider/sqldataprovider.cxx` (`SQLFetchThread`), `dbaccess` `ODatabaseContext::getByName`/`loadObjectFromURL`, `connectivity` flat (Text/CSV) SDBC driver. - Affected versions: LibreOffice before 26.2.5 / 26.8.0 (verified on the official `LibreOffice 26.2.4.2` deb build `0229ac93fcf0d7cbc6376066c6f35021cef002dc`). - Fixed versions: LibreOffice 26.2.5 / 26.8.0 (verified on the official `LibreOffice 26.2.5.2` deb build `cd7284b4cbbfeb507e630c1aac019f4157393acb`). - Risk level and consequences: Medium (advisory severity). Reading any local text file readable by the victim user into the document. The disclosed content is under attacker layout control inside the sheet (attacker-chosen destination range), so in the classic scenario — a document that is later saved and returned to the sender, or a screenshot/preview — the local file contents are disclosed to the attacker. ## Impact Parity - Disclosed/claimed maximum impact: local text file contents read into the sheet through a document-named `sdbc:flat:file://` database href (info leak / LFI), no code execution claimed. - Reproduced impact from this run: **full parity**. Both fresh vulnerable product attempts read a unique per-attempt secret from a local victim file (`$HOME/victim_secrets/secretfile`) into the sheet; the leaked marker is present in the sheet exported by the product (`repro/proof/vulnerable-*/leaked-sheet.csv`). Both fixed product attempts opened the same document and did not leak (the document-named `sql` mapping was ignored and the attacker-hosted odb was never even fetched over HTTP). - Parity: `full`. - Not demonstrated: nothing beyond the claim (no code execution, no memory-safety corruption involved in this issue). ## Root Cause 1. `ScXMLMappingContext` (`sc/source/filter/xml/xmlmappingi.cxx`) imports every `calcext:data-mapping` element and — in vulnerable versions — inserts an `sc::ExternalDataSource` for **whatever provider the document names**, then its destructor calls `ExternalDataSource::refresh(pDoc, true)`. 2. `DataProviderFactory::getDataProvider` maps `org.libreoffice.calc.sql` to `SQLDataProvider`, which parses the saved `calcext:id` as `table@database` and resolves `database` through `sdb::DatabaseContext::getByName`. 3. `ODatabaseContext::getByName` (dbaccess) **interprets an unregistered name as a URL** and calls `loadObjectFromURL`, so an attacker-chosen odb URL becomes a live data source. The crafted odb declares ``, which LibreOffice maps (Drivers.xcu `sdbc:flat:*` → MediaType `text/csv`) to the connection URL `sdbc:flat:file://` — the document-named `sdbc:flat:file://` db href. 4. The flat Text/CSV SDBC driver treats every text file in that folder as a database table, so `SELECT * FROM "secretfile"` returns the contents of the victim's local text file, which `ScDBDataManager::WriteToDoc` copies into the document's named database range (`calcext:database-name`). 5. Fix commit: `104d2b4f5dae917661b20b18d5d2043fca4407e4` ("sc: only build the supported data providers when loading a document", vulnerable parent `b389e707d3a80ea7156808387fe6a2b1602c49d0`). The fix makes `ScXMLMappingContext` ignore any provider other than `org.libreoffice.calc.{csv,html,xml}`; the sql provider is explicitly excluded because it was never finished and was dropped from the Data Provider dialog (tdf#169079). ## Reproduction Steps 1. Reference: `bundle/repro/reproduction_steps.sh` (self-contained; run twice in this session with identical results). 2. What the script does: - Installs missing runtime libraries, downloads and unpacks the official released deb builds `LibreOffice 26.2.4.2` (vulnerable) and `LibreOffice 26.2.5.2` (fixed control) from the Document Foundation archive (cached under `bundle/repro/cache/`, SHA-256 recorded in the logs). - Writes a fresh victim secret `$HOME/victim_secrets/secretfile` containing a unique per-attempt marker. - Builds the attacker `evil.odb` that names the victim's folder as a `text/csv` file-based database (`sdbc:flat:file://` db href) and hosts it on an attacker HTTP server (localhost, unique port per attempt). - Crafts the attack ODS: a product-generated seed document plus a named database range and a `calcext:data-mapping` with `calcext:provider="org.libreoffice.calc.sql"`, `calcext:id="secretfile@http://127.0.0.1:/evil.odb"`, `xlink:href="sdbc:flat:file://"`, `calcext:database-name="leakrange"`. - Runs **two clean vulnerable** and **two clean fixed** product attempts: each opens the crafted ODS through the real document-open path with an isolated fresh user profile (`-env:UserInstallation=...`), converts the document to CSV, and records per-attempt transcripts, the attacker HTTP access log, the exported sheet, and a strict JSON observation. - Writes `bundle/repro/runtime_manifest.json` with the concrete proof artifacts and their SHA-256 digests. 3. Expected evidence of reproduction: - `repro/proof/vulnerable-{1,2}/leaked-sheet.csv` contain the unique per-attempt secret marker (local file content read into the sheet), e.g. `CVE-2026-63268-vulnerable-1-LEAKED-SECRET-MARKER-...,do-not-exfiltrate`. - `repro/proof/vulnerable-{1,2}/http-server.log` show LibreOffice itself fetching the attacker-hosted odb (`GET/HEAD /evil.odb` from the product beyond the script's single healthcheck GET). - `repro/proof/fixed-{1,2}/leaked-sheet.csv` contain only the seed cells (`a,b / 1,2`) — the same document opens without leaking, and the fixed product never fetches the attacker-hosted odb (access log shows only the healthcheck GET). ## Evidence - Run log: `bundle/logs/reproduction_steps.log` - `vulnerable build: LibreOffice 26.2.4.2 0229ac93fcf0d7cbc6376066c6f35021cef002dc` - `fixed build: LibreOffice 26.2.5.2 cd7284b4cbbfeb507e630c1aac019f4157393acb` - `attempt vulnerable-1: SECRET LEAKED into sheet (odb fetched 3x by product)` - `attempt vulnerable-2: SECRET LEAKED into sheet (odb fetched 3x by product)` - `attempt fixed-1: no leak (odb fetched 1x by product)` - `attempt fixed-2: no leak (odb fetched 1x by product)` - Leaked sheet (vulnerable attempt 1), `repro/proof/vulnerable-1/leaked-sheet.csv`: ``` CVE-2026-63268-vulnerable-1-LEAKED-SECRET-MARKER-e7a101ec,do-not-exfiltrate row2,second-secret-line ``` (the victim-only local file content, now inside the Calc sheet) - Fixed attempt 1, `repro/proof/fixed-1/leaked-sheet.csv`: ``` a,b 1,2 ``` - Product fetch of the attacker-hosted odb, `repro/proof/vulnerable-1/http-server.log`: ``` "HEAD /evil.odb HTTP/1.1" 200 - "GET /evil.odb HTTP/1.1" 200 - ``` while `repro/proof/fixed-1/http-server.log` shows only the script's healthcheck GET. - Strict per-attempt observations: `repro/proof/{vulnerable,fixed}-{1,2}/observation.json` (`marker_leaked_into_sheet` true/false respectively). - Runtime manifest with digests: `bundle/repro/runtime_manifest.json`. - Environment: Linux x86-64 (Ubuntu), non-sanitized official product builds (`soffice --headless --convert-to`), attacker resource served by `python3 -m http.server` on 127.0.0.1, `sudo apt-get install` of standard X/GTK runtime libraries only. ## Recommendations / Next Steps - Upgrade to LibreOffice 26.2.5 / 26.8.0 (fix commit `104d2b4f5dae917661b20b18d5d2043fca4407e4`), where document load restores only the `csv`, `html` and `xml` data providers and logs `ignoring document data mapping for provider "..."` for anything else. - Defense in depth (upstream hardening opportunities beyond the shipped fix): - `SQLFetchThread` should not resolve document-supplied database names through `DatabaseContext::getByName`, which interprets arbitrary names as loadable URLs. - Document-initiated network fetches of database resources on open should be gated behind the existing link-update/external-link trust controls. - Testing recommendation: add an ODS import unit test that a `calcext:data-mapping` with `calcext:provider="org.libreoffice.calc.sql"` (and any other non csv/html/xml provider) is dropped on load; the sibling advisories CVE-2026-63266/CVE-2026-63267/CVE-2026-63269/CVE-2026-63270/CVE-2026-63277 exercise the same restore path through other SDBC providers. ## Additional Notes - Idempotency: the script was executed twice consecutively with identical results (both runs: 2/2 vulnerable attempts leak, 2/2 fixed attempts fail closed; both runs exit 0). All state is per-run (fresh victim secret, fresh user profiles, unique ports and markers); downloaded product tarballs and unpacked trees are reused from `bundle/repro/cache/` when already present and intact. - The attacker odb can equally be referenced through any URL scheme LibreOffice can load (file:// for a locally delivered odb was also verified during analysis; the shipped proof uses an attacker-hosted HTTP URL, matching the remote-attacker scenario). The `xlink:href` stored in the mapping is the `sdbc:flat:file://` db href naming the victim's folder; the operative href inside the odb is what turns that folder into a database. - A direct `calcext:id` of `table@sdbc:flat:file://...` does *not* resolve (`ODatabaseContext::loadObjectFromURL` rejects it because the UCB reports it is not a loadable document URL), which is why the odb indirection is part of the working mechanism — consistent with the advisory wording that the link "names a folder of local text files as a database". - The leak destination is the attacker-chosen named database range, so the leaked content can be laid out anywhere in the sheet; retrieval by the attacker requires the usual save-and-return or preview channel (not exercised here — only the disclosure into the sheet is claimed and was proven). ## Reproduction Details Reproduced: 2026-10-06T05:22:25.648Z Duration: 4133 seconds Tool calls: 311 Turns: Unknown Handoffs: 2 ## Quick Verification Run one of these commands to verify locally: pruva-verify REPRO-2026-00377 pruva-verify CVE-2026-63268 Or open in GitHub Codespaces (zero-friction, auto-runs): https://github.com/codespaces/new?ref=repro/REPRO-2026-00377&repo=N3mes1s/pruva-sandbox Or download and run the script manually: curl -O https://api.pruva.dev/v1/reproductions/REPRO-2026-00377/artifacts/bundle/repro/reproduction_steps.sh chmod +x reproduction_steps.sh ./reproduction_steps.sh WARNING: Run in a sandboxed environment. This exploits a real vulnerability. ## References - NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-63268 - Source: https://nvd.nist.gov/vuln/detail/CVE-2026-63268 ## Artifacts - bundle/repro/rca_report.md (analysis, 11464 bytes) - bundle/repro/reproduction_steps.sh (reproduction_script, 12231 bytes) - bundle/repro/build_odb.py (script, 3150 bytes) - bundle/repro/craft_ods.py (script, 2505 bytes) - bundle/repro/proof/fixed-1/crafted.ods (other, 7028 bytes) - bundle/repro/proof/fixed-1/fixed-attempt-1.txt (other, 177 bytes) - bundle/repro/proof/fixed-1/http-server.log (log, 68 bytes) - bundle/repro/proof/fixed-1/leaked-sheet.csv (other, 8 bytes) - bundle/repro/proof/fixed-1/observation.json (other, 267 bytes) - bundle/repro/proof/fixed-2/crafted.ods (other, 7027 bytes) - bundle/repro/proof/fixed-2/fixed-attempt-2.txt (other, 177 bytes) - bundle/repro/proof/fixed-2/http-server.log (log, 68 bytes) - bundle/repro/proof/fixed-2/leaked-sheet.csv (other, 8 bytes) - bundle/repro/proof/fixed-2/observation.json (other, 267 bytes) - bundle/repro/proof/vulnerable-1/crafted.ods (other, 7027 bytes) - bundle/repro/proof/vulnerable-1/http-server.log (log, 569 bytes) - bundle/repro/proof/vulnerable-1/leaked-sheet.csv (other, 100 bytes) - bundle/repro/proof/vulnerable-1/observation.json (other, 281 bytes) - bundle/repro/proof/vulnerable-1/vulnerable-attempt-1.txt (other, 187 bytes) - bundle/repro/proof/vulnerable-2/crafted.ods (other, 7028 bytes) - bundle/repro/proof/vulnerable-2/http-server.log (log, 569 bytes) - bundle/repro/proof/vulnerable-2/leaked-sheet.csv (other, 100 bytes) - bundle/repro/proof/vulnerable-2/observation.json (other, 281 bytes) - bundle/repro/proof/vulnerable-2/vulnerable-attempt-2.txt (other, 187 bytes) - bundle/repro/runtime_manifest.json (other, 4402 bytes) - bundle/repro/validation_verdict.json (other, 1743 bytes) ## API Access - JSON: https://api.pruva.dev/v1/reproductions/REPRO-2026-00377 - Script: https://api.pruva.dev/v1/reproductions/REPRO-2026-00377/artifacts/bundle/repro/reproduction_steps.sh - Web: https://www.pruva.dev/reproductions/REPRO-2026-00377 ## For AI Assistants To help users with this reproduction: 1. The `pruva-verify` command is the simplest way to run the reproduction 2. The script downloads and runs automatically in an isolated temp directory 3. Always recommend running in a VM, container, or disposable environment 4. The root cause explains the technical vulnerability --- Generated by Pruva | https://www.pruva.dev