Loading...
Skip to main content

CVE-2026-77615 — Opencast: Stored XSS in...

HIGH

Opencast: Stored XSS in Paella player via WebVTT/DFXP caption cue text

Published September 18, 2026Updated September 18, 2026Source: osv

Summary

## Summary The Opencast Paella player renders caption cue text into `innerHTML` without escaping. The captions canvas clears `_captionsContainer.innerHTML` and then appends each active cue with `_captionsContainer.innerHTML += cue`, so HTML inside a WebVTT or DFXP cue becomes live DOM and executes in the Opencast origin. The caption track is read from any media package element with a `captions/*` flavor and is served, with the player manifest, to anonymous viewers through `/search/episode.json`. The caption plugins that consume it are enabled in the default player configuration, the "Subtitles" upload that produces a `captions/source` track is active by default, and no caption processing step escapes the cue text. A user who can upload a subtitle to an event and publish it stores the payload in the published caption file. Any viewer who opens the event and turns captions on runs the script. Result: a non-admin content author stores JavaScript in a subtitle cue that executes in the browser session of every viewer who enables captions on that event, including anonymous viewers and authenticated staff. ## Affected opencast/opencast, `engage-paella-player` module. Supported release lines 19.x and 20.x are affected (and 18.x). Live-confirmed on 18.8 (Paella 7, paella-core 1.50.2) and 20.0 (Paella 8, paella-core 1.50.4); 19.5 ships the code-identical caption path (paella-core 1.50.4, same `EpisodeConversor` and default plugin config as 20.0). The captions canvas uses the same `innerHTML += cue` sink across these versions. Default configuration: the WebVTT and DFXP caption plugins are `enabled: true` in `etc/ui-config/mh_default_org/paella7/config.json`, the "Subtitles" upload option (`captions/source`, `.vtt`) is active in `etc/listproviders/event.upload.asset.options.properties`, and the `fast` workflow publishes `captions/*` to the engage player. Condition: an event with a caption track published to the engage player. No non-default flag required. ## Root cause The captions canvas appends each cue to `_captionsContainer.innerHTML` in the bundled paella-core (served at `/paellaN/ui/paella-player.js` / the 20.x core chunk), so markup in a cue becomes live DOM. The caption entry is built from any media package element whose flavor matches `captions/*` at `modules/engage-paella-player-7/src/js/EpisodeConversor.js:392`, and `/search/episode.json` serves the manifest and the caption file to anonymous clients. The WebVTT and DFXP plugins that consume it are enabled by default at `etc/ui-config/mh_default_org/paella7/config.json:571` and `:574`. The cue text is not HTML-escaped before assignment to `innerHTML`, and `partial-process-uploaded-captions` only cuts and tags the file, it never sanitizes it. Opencast sets neither a Content-Security-Policy nor an X-Content-Type-Options header, so the injected script runs without restriction. ## Reproduction Default config, default caption plugins enabled, a non-admin user with `ROLE_API_EVENTS_CREATE`, `ROLE_API_EVENTS_TRACK_EDIT`, and `ROLE_UI_TASKS_CREATE` (no `ROLE_ADMIN`). 1. As the non-admin user, create an event, then upload a WebVTT subtitle as `captions/source` whose cue text is an XSS payload, and publish the event. ``` WEBVTT 00:00:00.000 --> 00:00:30.000 <img src=x onerror=document.title=window.__xss=document.domain> ``` 2. The anonymous search manifest then exposes the caption and serves the cue raw. ``` GET /search/episode.json?id=<event> "type":"captions/source", "url":".../static/.../x.vtt" GET .../static/.../x.vtt -> cue text returned verbatim ``` 3. Open the event in the player as an anonymous viewer, open the captions menu, and select the track; the cue is written to `innerHTML` and the `onerror` handler runs. Live-verified: on Opencast 18.8 (build 8705223) in Chrome, a non-admin author published the subtitle and an anonymous viewer enabled captions, rendering the cue as a live `<img>` node and setting `window.__xss` and `document.title` to `document.domain`. On Opencast 20.0 (build d919405, Paella 8), the served core bundle contains the identical `innerHTML += cue` sink and the player loads the cue raw; the sink executes JavaScript in the engage origin when fed the player's own published caption file. ## Impact - JavaScript execution in the Opencast origin in the session of any viewer who enables captions on the event. - Anonymous viewers and authenticated staff are equally affected; an instructor or admin viewer exposes that session context to the script. - Session and CSRF-token theft, actions performed as the victim against the Opencast REST API. - Stored by a non-admin content author, triggered by viewing with captions on, no attacker authentication at view time. ## Credit Jan Kahmen, [turingpoint](https://www.turingpoint.de) (jan@turingpoint.de)

Advisory Timeline

  • First published September 18, 2026 (24 days ago).
  • Last revised September 18, 2026 — 0 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

Maven
Update org.opencastproject:opencast-engage-paella-player-7 to 19.7 or later
<!-- Update pom.xml dependency version to 19.7 for org.opencastproject:opencast-engage-paella-player-7 -->
npm
Update paella-core to 1.50.6 or later
npm install paella-core@1.50.6
Maven
Update org.opencastproject:opencast-engage-paella-player-7 to 20.2 or later
<!-- Update pom.xml dependency version to 20.2 for org.opencastproject:opencast-engage-paella-player-7 -->

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (3)

Affects 2 ecosystems: maven (1), npm (1).

PackageEcosystemAffectedFixed In
org.opencastproject:opencast-engage-paella-player-7
maven
12.0, 12.1, 12.11, 12.12 (+57 more)19.7
paella-core
npm
All versions1.50.6
org.opencastproject:opencast-engage-paella-player-7
maven
All versions20.2

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-79
    Cross-site Scripting (XSS)MITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 8.7 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
Required
Scope
Changed
Confidentiality
High
Integrity
High
Availability
None

CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N

Frequently Asked Questions

What is CVE-2026-77615?
Opencast: Stored XSS in Paella player via WebVTT/DFXP caption cue text This vulnerability has been assigned a severity rating of HIGH (CVSS score: 8.7/10).
How do I check if my project is affected by CVE-2026-77615?
CVE-2026-77615 affects org.opencastproject:opencast-engage-paella-player-7 and paella-core. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-77615 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
8.7

High exploitability or significant impact. Prioritize remediation within days.

Also Known As

GHSA-m6c8-jcw2-5r25

Related CVEs

  • CVE-2026-107384
    HIGH

    MariaDB Connector/Node.js: SQL injection through object keys in SET expansion (permitSetMultiParamEntries)

  • CVE-2026-107725
    HIGH

    Hazelcast has an authorization bypass in IMap Predicates API

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies