What's the problem?
Across the codebase, we're using innerHTML heavily — over 376 times across 30+ files — to build and update the UI. In a lot of these places, dynamic values like note names, block labels, frequency values, and even raw user input are being dropped straight into HTML strings without any escaping or sanitization.
This means if any of those values ever contain something like <img src=x onerror=alert(1)>, it'll execute as real HTML/JavaScript in the user's browser. That's a textbook Cross-Site Scripting (XSS) vulnerability.
How bad is it?
The main risk comes from shared project files. Music Blocks lets users share .tb projects — if someone crafts a malicious project with script payloads hidden in block labels or note names, anyone who opens that project gets hit. The malicious code runs in the victim's browser the moment any widget (PhraseMaker, Music Keyboard, Status, etc.) tries to render those labels.
Where exactly?
Here are some of the worst offenders:
Direct user input → innerHTML (no escaping at all)
temperament.js — slider values written straight to the DOM:
// Line 536
docById("frequencydiv1").innerHTML = docById("frequencySlider1").value;
// Line 1482
docById("frequencydiv").innerHTML = docById("frequencySlider").value;
Block labels injected via template literals
phrasemaker.js:
// Line 663
cell.innerHTML = `${blockLabel}<br>${this.rowArgs[i]}`;
// Line 681
cell.innerHTML = `${blockLabel}<br>${this.rowArgs[i][0]} ${this.rowArgs[i][1]}`;
// Line 2575
exportLabel.innerHTML = blockLabel + "<br>" + this.rowArgs[i];
Layout/note data injected without escaping
musickeyboard.js:
// Line 1574
cell.innerHTML = this.displayLayout[i].voice;
// Line 2534
cell.innerHTML = this.layout[index].noteName + this.layout[index].noteOctave.toString();
Attack scenario
Attacker creates a .tb project file with a block label like:
Shares it via Planet or sends the file directly
Victim opens the project in Music Blocks
Any widget that renders that block label (PhraseMaker, Music Keyboard, etc.) injects it via innerHTML
The attacker's script runs — can steal cookies, modify saved projects, or redirect the user
What's the problem?
Across the codebase, we're using
innerHTMLheavily — over 376 times across 30+ files — to build and update the UI. In a lot of these places, dynamic values like note names, block labels, frequency values, and even raw user input are being dropped straight into HTML strings without any escaping or sanitization.This means if any of those values ever contain something like
<img src=x onerror=alert(1)>, it'll execute as real HTML/JavaScript in the user's browser. That's a textbook Cross-Site Scripting (XSS) vulnerability.How bad is it?
The main risk comes from shared project files. Music Blocks lets users share
.tbprojects — if someone crafts a malicious project with script payloads hidden in block labels or note names, anyone who opens that project gets hit. The malicious code runs in the victim's browser the moment any widget (PhraseMaker, Music Keyboard, Status, etc.) tries to render those labels.Where exactly?
Here are some of the worst offenders:
Direct user input → innerHTML (no escaping at all)
temperament.js — slider values written straight to the DOM:
Block labels injected via template literals
phrasemaker.js:
Layout/note data injected without escaping
musickeyboard.js:
Attack scenario
Attacker creates a .tb project file with a block label like:
Shares it via Planet or sends the file directly
Victim opens the project in Music Blocks
Any widget that renders that block label (PhraseMaker, Music Keyboard, etc.) injects it via innerHTML
The attacker's script runs — can steal cookies, modify saved projects, or redirect the user