VYPR
Medium severity6.5NVD Advisory· Published May 18, 2026· Updated May 19, 2026

CVE-2026-27737

CVE-2026-27737

Description

BigBlueButton is an open-source virtual classroom. In versions prior to 3.0.19, the recording playback (presentation format) was not sanitizing user's input in public chat. This allowed for a malicious actor to craft and carry out a targeted XSS attack, activated on anyone replaying the recording. This issue has been fixed 3.0.19.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

BigBlueButton before 3.0.19 had a stored XSS in recording playback via unsanitized public chat input, allowing attacker to execute arbitrary JavaScript when replaying.

Vulnerability

BigBlueButton versions prior to 3.0.19 are vulnerable to a stored cross-site scripting (XSS) attack in the recording playback (presentation format). The public chat input was not sanitized before being rendered during playback, allowing an attacker to inject malicious HTML/JavaScript. The vulnerability resides in the bbb-playback component where dangerouslySetInnerHTML was used without sanitization [2]. Affected: BigBlueButton < 3.0.19.

Exploitation

An attacker must be able to participate in a meeting and send a crafted message in public chat. The malicious payload is stored in the recording. When any user replays that recording, the payload executes in the context of the playback page. No additional authentication or user interaction beyond replaying the recording is required [2].

Impact

Successful exploitation allows the attacker to execute arbitrary JavaScript in the browser of any user viewing the recording. This could lead to data theft, session hijacking, or other client-side attacks within the BigBlueButton domain. The attack targets the confidentiality and integrity of the user's session [1][2].

Mitigation

The vulnerability is fixed in BigBlueButton 3.0.19 [1]. The fix adds DOMpurify sanitization to the Reply and Text components in the playback module [2]. Users should upgrade to version 3.0.19 or later. No workaround is available. The CVE is not listed on CISA's Known Exploited Vulnerabilities (KEV) as of the publication date.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

2
69f45aa1b963

Merge pull request #24391 from bigbluebutton/antobinary-patch-8

https://github.com/bigbluebutton/bigbluebuttonAnton GeorgievDec 17, 2025via nvd-ref
1 file changed · +1 1
  • bbb-playback.placeholder.sh+1 1 modified
    @@ -1,3 +1,3 @@
     #!/bin/bash
     
    -git clone --branch v5.4.2 --depth 1 https://github.com/bigbluebutton/bbb-playback bbb-playback
    +git clone --branch v5.4.3 --depth 1 https://github.com/bigbluebutton/bbb-playback bbb-playback
    
09e89bfe4ff8

Merge pull request #330 from defnull/develop

https://github.com/bigbluebutton/bbb-playbackAnton GeorgievDec 9, 2025via nvd-ref
5 files changed · +24 11
  • package.json+4 3 modified
    @@ -7,6 +7,7 @@
         "bowser": "^2.11.0",
         "classnames": "^2.3.1",
         "darkreader": "^4.9.46",
    +    "dompurify": "^3.3.0",
         "linkify-react": "^3.0.4",
         "linkifyjs": "^3.0.5",
         "prop-types": "^15.8.1",
    @@ -15,13 +16,13 @@
         "react-intl": "^6.2.5",
         "react-router-dom": "^6.4.3",
         "react-sizeme": "^3.0.2",
    +    "recharts": "^2.12.7",
         "sass": "^1.52.1",
         "semver": "^7.5.2",
    +    "styled-components": "^6.1.13",
         "tldraw-v1": "npm:@tldraw/tldraw@^1.2.7",
         "video.js": "^7.21.1",
    -    "videojs-seek-buttons": "^3.0.1",
    -    "recharts": "^2.12.7",
    -    "styled-components": "^6.1.13"
    +    "videojs-seek-buttons": "^3.0.1"
       },
       "devDependencies": {
         "react-scripts": "^5.0.1"
    
  • package-lock.json+13 4 modified
    @@ -13,6 +13,7 @@
             "bowser": "^2.11.0",
             "classnames": "^2.3.1",
             "darkreader": "^4.9.46",
    +        "dompurify": "^3.3.0",
             "linkify-react": "^3.0.4",
             "linkifyjs": "^3.0.5",
             "prop-types": "^15.8.1",
    @@ -7804,10 +7805,10 @@
           "license": "MIT"
         },
         "node_modules/@types/trusted-types": {
    -      "version": "2.0.3",
    -      "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
    -      "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
    -      "dev": true
    +      "version": "2.0.7",
    +      "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
    +      "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
    +      "devOptional": true
         },
         "node_modules/@types/ws": {
           "version": "8.18.1",
    @@ -10938,6 +10939,14 @@
             "url": "https://github.com/fb55/domhandler?sponsor=1"
           }
         },
    +    "node_modules/dompurify": {
    +      "version": "3.3.0",
    +      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.0.tgz",
    +      "integrity": "sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==",
    +      "optionalDependencies": {
    +        "@types/trusted-types": "^2.0.7"
    +      }
    +    },
         "node_modules/domutils": {
           "version": "2.8.0",
           "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
    
  • src/components/chat/messages/reply/index.js+3 2 modified
    @@ -2,6 +2,7 @@ import React from 'react';
     import PropTypes from 'prop-types';
     import cx from 'classnames';
     import '../index.scss';
    +import DOMPurify from 'dompurify';
     
     const propTypes = {
       active: PropTypes.bool,
    @@ -34,9 +35,9 @@ const Reply = ({
       return (
         <span
           onClick={handleClickReply}
    -      className={cx('reply-tag', {inactive: !active})}
    +      className={cx('reply-tag', 'text-vanilla', {inactive: !active})}
    +      dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(text) }}
         >
    -      {text}
         </span>
       );
     };
    
  • src/components/chat/messages/user/text.js+2 1 modified
    @@ -1,5 +1,6 @@
     import React from 'react';
     import PropTypes from 'prop-types';
    +import DOMPurify from 'dompurify';
     
     const propTypes = {
       active: PropTypes.bool,
    @@ -21,7 +22,7 @@ const Text = ({
       return (
         <div
           className='text-vanilla'
    -      dangerouslySetInnerHTML={{ __html: text }}
    +      dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(text) }}
         />
       );
     };
    
  • src/components/notes/index.js+2 1 modified
    @@ -6,6 +6,7 @@ import {
     import { ID } from 'utils/constants';
     import storage from 'utils/data/storage';
     import './index.scss';
    +import DOMPurify from 'dompurify';
     
     const intlMessages = defineMessages({
       aria: {
    @@ -26,7 +27,7 @@ const Notes = () => {
         >
           <div className="notes">
             <div
    -          dangerouslySetInnerHTML={{ __html: storage.notes }}
    +          dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(storage.notes) }}
               style={{ width: '100%' }}
             />
           </div>
    

Vulnerability mechanics

Root cause

"User-controlled chat text and shared notes content are rendered via dangerouslySetInnerHTML without sanitization, enabling stored cross-site scripting."

Attack vector

An authenticated attacker posts a malicious message in the public chat or shared notes during a BigBlueButton session. The message contains HTML/JavaScript payloads that are not sanitized before being stored. When any user replays the recorded session (presentation format), the unsanitized payload is rendered via dangerouslySetInnerHTML in the playback UI [CWE-79]. The attack requires only a valid session account (PR:L) and no user interaction beyond viewing the recording.

Affected code

The vulnerability exists in the bbb-playback component (v5.4.2 and earlier). Three React components render unsanitized user input via dangerouslySetInnerHTML: src/components/chat/messages/user/text.js (public chat messages), src/components/chat/messages/reply/index.js (reply tags), and src/components/notes/index.js (shared notes). The bbb-playback.placeholder.sh script in the main BigBlueButton repo pins the playback version [patch_id=424398].

What the fix does

The patch adds the DOMPurify library (v3.3.0) as a dependency [patch_id=424397] and wraps every dangerouslySetInnerHTML call with DOMPurify.sanitize(). Three files are changed: src/components/chat/messages/user/text.js sanitizes public chat messages, src/components/chat/messages/reply/index.js sanitizes reply tags, and src/components/notes/index.js sanitizes shared notes content. By passing user-controlled HTML through DOMPurify before injection into the DOM, the fix strips malicious scripts and event handlers while preserving safe markup.

Preconditions

  • authAttacker must have a valid account on the BigBlueButton server (PR:L).
  • inputAttacker must be able to post messages in public chat or shared notes during a session.
  • networkA victim must replay the recorded session using the presentation playback format.

Generated on May 19, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.