CVE-2020-36826
Description
A vulnerability was found in AwesomestCode LiveBot. It has been classified as problematic. Affected is the function parseSend of the file js/parseMessage.js. The manipulation leads to cross site scripting. It is possible to launch the attack remotely. This product is using a rolling release to provide continious delivery. Therefore, no version details for affected nor updated releases are available. Upgrading to version 0.1 is able to address this issue. The name of the patch is 57505527f838d1e46e8f93d567ba552a30185bfa. It is recommended to upgrade the affected component. The identifier of this vulnerability is VDB-257784.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A stored XSS vulnerability in LiveBot's parseMessage function allows remote attackers to inject arbitrary HTML/JavaScript via crafted messages.
Vulnerability
CVE-2020-36826 is a cross-site scripting (XSS) vulnerability found in the parseMessage function within the js/parseMessage.js file of the AwesomestCode LiveBot project [1]. The root cause is insufficient sanitization of user-supplied input. Specifically, the original regular expression used to strip HTML tags failed to properly escape < and > characters, allowing malicious markup to pass through when the message was rendered [2].
Exploitation
The vulnerability can be exploited remotely without authentication [1]. An attacker sends a crafted message containing JavaScript payloads wrapped in HTML tags. Because the parseSend function does not securely escape angle brackets, the unescaped content is later processed by parseMessage and displayed to other users, leading to stored XSS [2].
Impact
Successful exploitation enables an attacker to execute arbitrary JavaScript in the context of other users' sessions. This can lead to theft of authentication tokens, session hijacking, defacement, or redirection to malicious sites [1].
Mitigation
The vendor addressed the issue in commit 57505527f838d1e46e8f93d567ba552a30185bfa and released version 0.1 [2]. The fix replaces the flawed regex-based removal with separate replacements for < and > using String.prototype.replace(), properly HTML-encoding the input [2]. All users are advised to upgrade to the latest rolling release.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1- Range: <0.1
Patches
35e5713b32787Major login fix, DM sorting, Another fix
4 files changed · +38 −36
js/dmList.js+22 −22 modified@@ -3,50 +3,50 @@ function mutualGuilds(u, g, remove){ if(!u.mutualGuilds){ u.mutualGuilds = new Discord.Collection(); bot.guilds.cache.forEach(g => { - let inGuild = g.members.cache.get(u.id) + if(!g.available) return; + let inGuild = g.members.cache.get(u.id); if (inGuild && !u.mutualGuilds.get(u.id)){ - u.mutualGuilds.set(g.id, g) + u.mutualGuilds.set(g.id, g); } else if (!inGuild && u.mutualGuilds.get(u.id)){ - u.mutualGuilds.delete(g.id) + u.mutualGuilds.delete(g.id); } }) return; } + let mutualGuild = u.mutualGuilds.get(g.id) - if(remove && mutualGuild){ - u.mutualGuilds.delete(g.id) - } else if (!remove && !mutualGuild) { - u.mutualGuilds.set(g.id, g) - } + + if(remove && mutualGuild) + u.mutualGuilds.delete(g.id); + else if (!remove && !mutualGuild) + u.mutualGuilds.set(g.id, g); } function updateUsers(bunch, m = undefined, remove = false){ if(bunch || !m){ bot.users.cache.forEach(u => { u.openDM != true && u.openDM != false ? u.openDM = false : undefined; - u.mutualGuilds ? undefined : mutualGuilds(u) + u.mutualGuilds ? undefined : mutualGuilds(u); u.received ? true : false; }); return; } - if(user.openDM == undefined) - user.openDM = false; + if(m.user.openDM == undefined) + m.user.openDM = false; - if(m){ - mutualGuilds(u.user, m.guild, remove) - } + if(m) + mutualGuilds(m.user, m.guild, remove); } function updateUserDM(c, u){ - if(c.type != 'dm' || u.bot) return - if(selectedChan == c) return u.received = false + if(c.type != 'dm' || u.bot) return; + if(selectedChan == c) return u.received = false; u.received = true; } function dmList(){ - - // If the guild is selected then hide the guild indicator + // If a guild is selected then hide the guild indicator if(selectedGuild){ document.getElementById('guildIndicator').style.display = 'none'; selectedGuild = undefined; @@ -117,14 +117,14 @@ function dmList(){ // Note: You can't message bots with a bot account, only users bot.users.cache.array() // Map the users .filter(u => u.mutualGuilds && u.mutualGuilds.size && !u.bot) - .sort((u1, u2) => u1.username - u2.username) + .sort((u1, u2) => u1.username.localeCompare(u2.username)) .forEach(u => { // Get the element for the user - let [open, received, other] = categories + let [open, received, other] = categories; // Create the dm channel let div = document.createElement("div"); - div.classList.add('dmChannel') + div.classList.add('dmChannel'); div.id = u.id; // Create the image for the user if they have one, otherwise use discords default and animate it on hover @@ -166,7 +166,7 @@ function dmList(){ if (id != u.id) { div.classList.add("selectedChan"); - dmChannelSelect(u, div) + dmChannelSelect(u, div); } })
js/load.js+2 −2 modified@@ -178,12 +178,12 @@ let load = token => { }); // Runs when a user joins a server - bot.on('guildmemberAdd', m => { + bot.on('guildMemberAdd', m => { updateUsers(false, m); }) // Runs when a user leaves a server - bot.on('guildmemberRemove', m => { + bot.on('guildMemberRemove', m => { updateUsers(false, m, true); })
js/setToken.js+11 −11 modified@@ -1,14 +1,11 @@ async function setToken(token) { let client = new Discord.Client(); - let error = false; + let error = [false, 'none']; if(global.bot && bot.token == token) {errorHandler('SAME-TOKEN'); return 'SAME-TOKEN'} try { - if(!token.replace(/ /, '').length){ - errorHandler('EMPTY-TOKEN'); + if(!token.replace(/ /, '').length) throw('EMPTY-TOKEN') - } await client.login(token).catch(err => { - errorHandler(err) throw (err) }); client.destroy(); @@ -21,7 +18,7 @@ async function setToken(token) { // Delete the list of the guilds let guildContainer = document.getElementById('guildContainer'); - if(guildContainer.parentElement){ + if(guildContainer && guildContainer.parentElement){ guildContainer.parentElement.removeChild(guildContainer); } @@ -39,7 +36,7 @@ async function setToken(token) { bot.destroy(); } await unloadAllScripts(); - unloadThemes() + await unloadThemes() load(token); document.getElementById('tokenbox').style.borderColor = '#313339'; cachedGuilds = [] @@ -49,7 +46,8 @@ async function setToken(token) { tokenBox.animate(animations.flashRed); // Set the error to true so it doesn't save the token - error = true + error[0] = true + error[1] = err } document.getElementById('tokenbox').value = ''; // Return if there's been an error or not @@ -60,9 +58,11 @@ async function setToken(token) { // Will be upgraded to database eventually async function saveToken(token) { let error = await setToken(token) - if(!error){ + if(!error[0]){ settings.token = token; localStorage.setItem('livebot-token', token); - } else - console.warn(`The token won't be saved since there was an error`) + } else { + errorHandler(error[1]) + console.warn(`The token won't be saved since there was an error`) + } } \ No newline at end of file
js/userSettings.js+3 −1 modified@@ -74,7 +74,9 @@ function openPopup(category, group){ if (category.classList.contains("toggledOn")) { createPopup(category.parentElement, group); } else { - category.parentElement.querySelector(".settingsPopup").remove(); + let settingsPopout = category.parentElement.querySelector(".settingsPopup") + if(settingsPopout) + settingsPopout.remove(); } }
57505527f838Fixed a serious vulnerability
1 file changed · +5 −2
js/parseMessage.js+5 −2 modified@@ -14,10 +14,13 @@ let parseSend = (text) => { } let parseMessage = (text, msg = null, embed = false) => { - // Remove html in the message - let textContent = text.replace(/(<)([^>]+)(>)/gm, '<$2>'); + // Remove html < and > in the message + let textContent = text + .replace(/</g, '<') + .replace(/>/g, '>'); // General message parsing + // Match links textContent = textContent.replace(/https?:\/\/.+?(\/(.+?(\?.+?((?= )|$)))|(?= )|$)/mg, '<a href="$&" rel="noreferrer noopener" title="$&" target="_blank">$&</a>'); // Add html tags for markup
57505527f838Fixed a serious vulnerability
1 file changed · +5 −2
js/parseMessage.js+5 −2 modified@@ -14,10 +14,13 @@ let parseSend = (text) => { } let parseMessage = (text, msg = null, embed = false) => { - // Remove html in the message - let textContent = text.replace(/(<)([^>]+)(>)/gm, '<$2>'); + // Remove html < and > in the message + let textContent = text + .replace(/</g, '<') + .replace(/>/g, '>'); // General message parsing + // Match links textContent = textContent.replace(/https?:\/\/.+?(\/(.+?(\?.+?((?= )|$)))|(?= )|$)/mg, '<a href="$&" rel="noreferrer noopener" title="$&" target="_blank">$&</a>'); // Add html tags for markup
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
0No linked articles in our index yet.