diff --git a/.common/utils/helpers.js b/.common/utils/helpers.js
index d7c4b99..77d6ca5 100644
--- a/.common/utils/helpers.js
+++ b/.common/utils/helpers.js
@@ -709,4 +709,57 @@ function VersionCheck(requiredVersion, installedVersion) {
// 4. PERFECT: Installed version meets or exceeds the required baseline.
console.log(`VersionCheck: Installed version meets or exceeds the required baseline. Required: ${requiredVersion}, Installed: ${installedVersion}`);
return 'compatible';
+}
+
+function SanitizeHTML(htmlString) {
+ // 1. Parse the string into a temporary DOM document
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(htmlString, 'text/html');
+
+ // 2. Define allowed tags and attributes
+ const allowedTags = ['IMG', 'SPAN', 'B', 'I', 'BR', 'EM', 'STRONG'];
+ const allowedAttrs = ['src', 'class'];
+
+ // 3. Walk through all elements in the parsed document
+ const allElements = doc.body.querySelectorAll('*');
+ allElements.forEach(el => {
+ // Check if it's an
tag and enforce class restrictions
+ if (el.tagName === 'IMG') {
+ const className = el.getAttribute('class') || '';
+ // Split classes by whitespace in case there are multiple (e.g., class="emote custom")
+ const classes = className.split(/\s+/);
+
+ // Must contain either 'emote' or 'bits' to be allowed
+ const hasValidClass = classes.includes('emote') || classes.includes('bits');
+
+ if (!hasValidClass) {
+ // Unwrap or remove the unauthorized
tag
+ const parent = el.parentNode;
+ while (el.firstChild) {
+ parent.insertBefore(el.firstChild, el);
+ }
+ parent.removeChild(el);
+ return;
+ }
+ }
+
+ // If any other tag isn't in our allowed list, unwrap it
+ if (!allowedTags.includes(el.tagName)) {
+ const parent = el.parentNode;
+ while (el.firstChild) {
+ parent.insertBefore(el.firstChild, el);
+ }
+ parent.removeChild(el);
+ return;
+ }
+
+ // Strip out any attributes not explicitly allowed (like onerror, onload, etc.)
+ Array.from(el.attributes).forEach(attr => {
+ if (!allowedAttrs.includes(attr.name.toLowerCase())) {
+ el.removeAttribute(attr.name);
+ }
+ });
+ });
+
+ return doc.body.innerHTML;
}
\ No newline at end of file
diff --git a/printer-bot/contents/script.js b/printer-bot/contents/script.js
index 5fa6563..b705cfb 100644
--- a/printer-bot/contents/script.js
+++ b/printer-bot/contents/script.js
@@ -51,7 +51,7 @@ async function CustomEvent(data) {
subtitleEl.innerText = `${data.user}`;
const messageEl = document.createElement('div');
- messageEl.innerHTML = data.message;
+ messageEl.innerHTML = SanitizeHTML(data.message);
// Render emotes
for (i in data.emotes) {
@@ -116,7 +116,7 @@ async function CustomEvent(data) {
const messageEl = document.createElement('div');
messageEl.innerHTML = `${data.cumulative} months${data.monthStreak > 1 ? ' (' + data.monthStreak + ' in a row!)' : ''}`;
if (data.messageStripped)
- messageEl.innerHTML += `
${data.messageStripped}`;
+ messageEl.innerHTML += `
${SanitizeHTML(data.messageStripped)}`;
contentEl.appendChild(messageEl);
@@ -196,7 +196,7 @@ async function CustomEvent(data) {
subtitleEl.innerText = `${data.user}`;
const messageEl = document.createElement('div');
- messageEl.innerHTML = data.rawInput;
+ messageEl.innerHTML = SanitizeHTML(data.rawInput);
// // Render emotes
// for (i in data.emotes) {
@@ -284,7 +284,7 @@ async function CustomEvent(data) {
const messageEl = document.createElement('div');
messageEl.innerHTML = `${data.user}
sent a Super Chat!`;
if (data.message)
- messageEl.innerHTML += `
${data.message}`;
+ messageEl.innerHTML += `
${SanitizeHTML(data.message)}`;
contentEl.appendChild(messageEl);
@@ -424,7 +424,7 @@ async function CustomEvent(data) {
if (data.tipMessage) {
const messageEl = document.createElement('div');
- messageEl.innerHTML = `${data.tipMessage}`;
+ messageEl.innerHTML = `${SanitizeHTML(data.tipMessage)}`;
contentEl.appendChild(messageEl);
}
@@ -448,7 +448,7 @@ async function CustomEvent(data) {
if (data.donationMessage) {
const messageEl = document.createElement('div');
- messageEl.innerHTML = `${data.donationMessage}`;
+ messageEl.innerHTML = `${SanitizeHTML(data.donationMessage)}`;
contentEl.appendChild(messageEl);
}
@@ -475,7 +475,7 @@ async function CustomEvent(data) {
if (data["fw.message"]) {
const messageEl = document.createElement('div');
- messageEl.innerHTML = `${data["fw.message"]}`;
+ messageEl.innerHTML = `${SanitizeHTML(data["fw.message"])}`;
contentEl.appendChild(messageEl);
}
@@ -537,7 +537,7 @@ async function CustomEvent(data) {
if (customMessage) {
const txt = document.createElement("textarea");
txt.innerHTML = customMessage;
- customMessageEl.innerHTML += `
${txt.value}`;
+ customMessageEl.innerHTML += `
${SanitizeHTML(txt.value)}`;
}
// Add a cute thank you message because you're uwu like that