CVE-2026-77615
Paella Player: Stored XSS via caption cue text
Paella Player is a set of libraries to create a multi stream video player. Prior to Paella Player 2.12.11 (as used in Opencast prior to 19.7 and 20.2), there is a potential XSS attack though closed captions cue text. This vulnerability is fixed in 2.12.11.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- Required
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
8.7
Paella Player: Stored XSS via caption cue text
Paella Player is a set of libraries to create a multi stream video player. Prior to Paella Player 2.12.11 (as used in Opencast prior to 19.7 and 20.2), there is a potential XSS attack though closed captions cue text. This vulnerability is fixed in 2.12.11.
- Record
CVE-2026-77615- CVSS 3.1
- 8.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N - Weakness
- CWE-79
- Updated
- 2026-11-02
EUVDEUVD-2026-82473
8.7
Paella Player is a set of libraries to create a multi stream video player. Prior to Paella Player 2.12.11 (as used in Opencast prior to 19.7 and 20.2), there is a potential XSS attack though closed captions cue text. This vulnerability is fixed in 2.12.11.
- Record
EUVD-2026-82473- CVSS 3.1
- 8.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-m6c8-jcw2-5r25
8.7
Opencast: Stored XSS in Paella player via WebVTT/DFXP caption cue text
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).
- As the non-admin user, create an event, then upload a WebVTT subtitle as
captions/sourcewhose 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>
- 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
- Open the event in the player as an anonymous viewer, open the captions menu, and select the track; the cue is written to
innerHTMLand theonerrorhandler 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.…
- Record
GHSA-m6c8-jcw2-5r25- CVSS 3.1
- 8.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N - Weakness
- CWE-79
- Updated
- 2026-11-02
NVD
8.7
Paella Player is a set of libraries to create a multi stream video player. Prior to Paella Player 2.12.11 (as used in Opencast prior to 19.7 and 20.2), there is a potential XSS attack though closed captions cue text. This vulnerability is fixed in 2.12.11.
- Record
CVE-2026-77615- CVSS 3.1
- 8.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N - Weakness
- CWE-79
- Updated
- 2026-11-02
OSV
8.7
Paella Player: Stored XSS via caption cue text
Paella Player is a set of libraries to create a multi stream video player. Prior to Paella Player 2.12.11 (as used in Opencast prior to 19.7 and 20.2), there is a potential XSS attack though closed captions cue text. This vulnerability is fixed in 2.12.11.
- Record
CVE-2026-77615- CVSS 3.1
- 8.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N - Weakness
- CWE-79
- Updated
- 2026-11-04
OSVGHSA-m6c8-jcw2-5r25
8.7
Opencast: Stored XSS in Paella player via WebVTT/DFXP caption cue text
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).
- As the non-admin user, create an event, then upload a WebVTT subtitle as
captions/sourcewhose 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>
- 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
- Open the event in the player as an anonymous viewer, open the captions menu, and select the track; the cue is written to
innerHTMLand theonerrorhandler 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.…
- Record
GHSA-m6c8-jcw2-5r25- CVSS 3.1
- 8.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N - Weakness
- CWE-79
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
org.opencastproject:opencast-engage-paella-player-7Maven |
before 19.7 | 19.7 |
org.opencastproject:opencast-engage-paella-player-7Maven |
20.0 up to 20.2 | 20.2 |
paella-corenpm |
before 1.50.6 | 1.50.6 |
org.opencastproject:opencast-engage-paella-player-7Maven |
before 19.7, plus listed versions 12.012.112.1112.1212.13 Show 45 moreShow less12.212.312.512.612.712.812.913.013.113.1013.1113.1213.213.413.613.713.814.014.114.1014.1114.1214.1314.214.314.514.614.714.814.915.015.115.1015.1115.1215.1315.215.315.415.515.615.715.815.916.0 |
19.7 |
History
| Recorded | Changed | Sources |
|---|---|---|
| facts | OSV | |
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-77615 is a high vulnerability (CVSS 8.7) in Opencast, published September 17, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.56%, the 46th percentile. Fixed in org.opencastproject:opencast-engage-paella-player-7 19.7.
References
github.com/opencast/opencast/security/advisories/GHSA-m6c8-jcw2-5r25
github.com/opencast/opencast/pull/7736
github.com/opencast/opencast/commit/701682c635f668228c3e8fb7b4564b3294788e40
github.com/polimediaupv/paella-core/commit/94a36490808ac5a1f60a0745d71ec9253f6d206b
github.com/polimediaupv/paella-core/commit/9b2f14ec4cf55efaf4c045c77a5ed8f5ec559ab4
github.com/polimediaupv/paella-player/commit/6fe4af7306044198c8e91e2e7f4128428b83cf03
Show 7 moreShow less
github.com/opencast/opencast/releases/tag/19.7
github.com/opencast/opencast/releases/tag/20.2
github.com/polimediaupv/paella-player/blob/a1b6c42467938a00a4b4d0b8c68435cd4f9d2a16/repos/paella-core/CHANGELOG.md?plain=1
nvd.nist.gov/vuln/detail/CVE-2026-77615
github.com/advisories/GHSA-m6c8-jcw2-5r25
github.com/CVEProject/cvelistV5/tree/main/cves/2026/77xxx/CVE-2026-77615.json
github.com/opencast/opencast
Left out here: 11 versions and the rest of 2 source descriptions. The JSON record has them.