# 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