# REPRO-2026-00378: LFI and GET SSRF via GStreamer and HLS playlists — linked media makes GStreamer read local files and fetch remote URLs on open ## Summary Status: published Severity: medium CVSS: 6.7 / 10 CWE: CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor) Type: security Confidence: high ## Identifiers REPRO ID: REPRO-2026-00378 CVE: CVE-2026-63269 ## Package Name: LibreOffice/core Ecosystem: unknown Affected: LibreOffice before 26.2.5 (26.2 line) and before 26.8.0; vulnerable baseline 26.2.4.x Fixed: 26.2.5 ## Root Cause # CVE-2026-63269 — Root Cause Analysis ## Summary LibreOffice documents can contain *linked* audio/video media objects (ODF `draw:plugin` inside a `draw:frame`, e.g. an Impress `MediaShape`). On Linux, LibreOffice plays such media through its `avmedia` GStreamer backend. In vulnerable versions, merely **opening** a document causes LibreOffice to hand the linked media URL to GStreamer's `playbin`, which resolves and prerolls the stream without any user interaction or link-update consent. If the linked media is an HLS playlist (`.m3u8`), GStreamer's `hlsdemux` follows every URI listed in the playlist — including `file://` URIs naming local files and `http(s)://` URLs naming arbitrary remote hosts — so a crafted document makes the victim's machine read local files and issue attacker-directed GET requests simply by being opened. ## Impact - **Package/component affected:** LibreOffice (avmedia GStreamer backend, `libavmediagst.so`; document media shapes in Impress/Draw). - **Affected versions:** LibreOffice < 26.2.5 / < 26.8.0 (reproduced on the TDF 26.2.4.2 Linux x86-64 deb build). - **Risk level and consequences:** Medium (CVSS 6.7 per advisory). Remote, unauthenticated attacker delivers a document; on open, the victim's LibreOffice performs: - **LFI:** local files named in the playlist are opened and read by GStreamer (`filesrc`), and their contents can end up in the document (per the advisory), enabling file disclosure. - **GET SSRF:** arbitrary remote URLs listed in the playlist are fetched from the victim host (here: `GStreamer souphttpsrc` HTTP requests), reaching internal/loopback services. ## Impact Parity - **Disclosed/claimed maximum impact:** LFI + GET SSRF via GStreamer following a document-linked HLS playlist (`expected_impact=ssrf`, surface `viewer_document`, entrypoint `open_document`). - **Reproduced impact from this run:** Full LFI + GET SSRF on document open through the real product (LibreOffice Impress 26.2.4.2 under Xvfb): the attacker HTTP server received the playlist GET and the SSRF segment GET from `GStreamer souphttpsrc`, and `strace` captured the soffice/GStreamer process tree opening the local secret file referenced by a `file://` playlist entry. Two independent vulnerable attempts reproduced both effects; two fixed-version (26.2.5.2) attempts fetched nothing at all. - **Parity:** `full` - **Not demonstrated:** exfiltration of the local file's *contents* back to the attacker (the advisory's "contents could end up in the document" leg); the local read itself and the remote fetch are both proven. ## Root Cause LibreOffice's media shape (`SdrMediaObj` / `avmedia::MediaWindow`) creates a GStreamer `playbin` for the persisted linked-media URL as soon as the slide containing the media object is displayed — which happens during document load for the first page — and sets it to the paused/preroll state to render a preview frame. Prerolling an HLS playlist makes `hlsdemux` download the manifest and then fetch every fragment URI it lists. Neither LibreOffice nor GStreamer restricted: 1. the scheme of fragment URIs inside a playlist served over HTTP (`file://` entries are honored by `filesrc`), or 2. the remote URLs a playlist can direct the player to (any `http(s)://` target is fetched by `souphttpsrc`). Additionally, linked media was loaded automatically on document open without being subject to LibreOffice's link-update consent. **Fix (LibreOffice 26.2.5 / 26.8.0, by Caolán McNamara):** per the advisory, "LibreOffice does not follow playlists that name further resources, and linked media is under link update control." In this run's negative control, the fixed 26.2.5.2 build did not even fetch the playlist when opening the same crafted document (linked media now requires link-update consent, suppressed in an unattended open), and a fortiori never followed playlist-listed resources. ## Reproduction Steps 1. `bundle/repro/reproduction_steps.sh` (self-contained; safe to re-run). 2. What it does: - Installs runtime deps (`xvfb`, `strace`, GStreamer good/bad/libav plugins) and downloads/extracts the official TDF deb builds LibreOffice 26.2.4.2 (vulnerable) and 26.2.5.2 (fixed) into the prepared project cache. - Generates a valid MPEG-TS fragment (so playback genuinely proceeds through the playlist instead of erroring on undecodable bytes). - For each attempt (2 vulnerable + 2 fixed), it: - starts a local "attacker" HTTP server (python3) that logs every request and serves `/stream.m3u8`; - writes an HLS playlist listing one remote URL (`http://127.0.0.1:PORT/ssrf-segment--.ts` — the SSRF probe) and one local file (`file://.../lfi-secret.txt` — the LFI probe); - generates a crafted ODP whose slide 1 contains a linked media object (`draw:plugin` with `draw:mime-type="application/vnd.sun.star.media"`) pointing at the playlist; - opens the document with the real `soffice` under Xvfb, tracing `openat()` with `strace -f`; - records playlist GETs, segment GETs, and local-file opens. 3. Expected evidence of reproduction: - Vulnerable attempts: `http.log` shows `GET /stream.m3u8` **and** `GET /ssrf-segment-...` with User-Agent `GStreamer souphttpsrc`; `lfi-evidence.txt` shows `openat(... "lfi-secret.txt" ...) = `. - Fixed attempts: neither the playlist nor the segment is fetched and the secret file is never opened. ## Evidence - Full run log: `bundle/logs/reproduction_steps.log` (run 1) and `bundle/logs/reproduction_steps_run2.log` (run 2). - Per-attempt proof under `bundle/repro/proof/-/`: - `http.log` — attacker-server request log, e.g. vulnerable-2: `GET /stream.m3u8 ua=GStreamer souphttpsrc 1.28.2 libsoup/3.6.6` followed by `GET /ssrf-segment-vulnerable-2.ts` (same UA). - `lfi-evidence.txt` — strace excerpt, e.g. vulnerable-1: `openat(AT_FDCWD, ".../proof/vulnerable-1/lfi-secret.txt", O_RDONLY) = 40`. - `stream.m3u8` — the exact playlist served; `soffice.log` — product stderr. - Machine-readable manifest with artifact hashes: `bundle/repro/runtime_manifest.json`. - Verdict: `bundle/repro/validation_verdict.json`. - Environment: Ubuntu 26.04 x86_64, LibreOffice 26.2.4.2 TDF deb (tarball sha256 `810ef197…4b9900`) vs LibreOffice 26.2.5.2 TDF deb (tarball sha256 `2f03bfb2…1bed1e`), GStreamer 1.28.2, Xvfb display, no sanitizers — real product binaries exercised through the real document-open path. ## Recommendations / Next Steps - Upgrade to LibreOffice ≥ 26.2.5 / ≥ 26.8.0 (fixed). - The fix approach per the advisory: do not follow playlists that name further resources in the media backend, and put linked media behind link-update consent. - Testing: open a document with a linked-media HLS playlist referencing `file://` and remote URLs; assert no outbound requests and no local file opens occur without explicit link-update consent. ## Additional Notes - **Idempotency:** the script was run twice consecutively; both runs produced the confirmed verdict (2/2 vulnerable attempts positive, 2/2 fixed attempts negative each run). Downloads/extractions are cached in the prepared project cache and reused across runs; proof directories are regenerated per run. - **Document format detail:** the ODF media link must use `draw:mime-type="application/vnd.sun.star.media"`; using an HLS-specific MIME type makes the ODF importer drop the URL (verified by round-tripping through the vulnerable build itself). The structure was derived from a reference document created programmatically via UNO (`com.sun.star.drawing.MediaShape.MediaURL`). - **Limitations:** content exfiltration of the read file into the saved document was not needed to prove the claim ("local file reads and remote fetches") and was not attempted; the read and fetch primitives are demonstrated directly. ## Reproduction Details Reproduced: 2026-10-06T05:22:31.669Z Duration: 7181 seconds Tool calls: 234 Turns: Unknown Handoffs: 2 ## Quick Verification Run one of these commands to verify locally: pruva-verify REPRO-2026-00378 pruva-verify CVE-2026-63269 Or open in GitHub Codespaces (zero-friction, auto-runs): https://github.com/codespaces/new?ref=repro/REPRO-2026-00378&repo=N3mes1s/pruva-sandbox Or download and run the script manually: curl -O https://api.pruva.dev/v1/reproductions/REPRO-2026-00378/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-63269 - Source: https://www.cve.org/CVERecord?id=CVE-2026-63269 ## Artifacts - bundle/repro/rca_report.md (analysis, 7990 bytes) - bundle/repro/reproduction_steps.sh (reproduction_script, 16995 bytes) - bundle/logs/reproduction_steps.log (log, 2535 bytes) - bundle/repro/proof/fixed-1/soffice.log (log, 41 bytes) - bundle/repro/proof/fixed-1/stream.m3u8 (other, 224 bytes) - bundle/repro/proof/fixed-2/soffice.log (log, 41 bytes) - bundle/repro/proof/fixed-2/stream.m3u8 (other, 224 bytes) - bundle/repro/proof/vulnerable-1/http.log (log, 994 bytes) - bundle/repro/proof/vulnerable-1/lfi-evidence.txt (other, 575 bytes) - bundle/repro/proof/vulnerable-1/soffice.log (log, 2753 bytes) - bundle/repro/proof/vulnerable-1/stream.m3u8 (other, 234 bytes) - bundle/repro/proof/vulnerable-2/http.log (log, 994 bytes) - bundle/repro/proof/vulnerable-2/lfi-evidence.txt (other, 460 bytes) - bundle/repro/proof/vulnerable-2/soffice.log (log, 2753 bytes) - bundle/repro/proof/vulnerable-2/stream.m3u8 (other, 234 bytes) - bundle/repro/runtime_manifest.json (other, 3018 bytes) - bundle/repro/validation_verdict.json (other, 1277 bytes) ## API Access - JSON: https://api.pruva.dev/v1/reproductions/REPRO-2026-00378 - Script: https://api.pruva.dev/v1/reproductions/REPRO-2026-00378/artifacts/bundle/repro/reproduction_steps.sh - Web: https://www.pruva.dev/reproductions/REPRO-2026-00378 ## 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