Use textContent instead of innerHTML

Previously, setting `innerHTML` was used to display the statuses.  These
could include content communicated from the remote VNC server, allowing
the remove VNC server to inject HTML into the noVNC page.

This commit switches all uses of `innerHTML` to use `textContent`, which
is not vulnerable to the HTML injection.
This commit is contained in:
Solly Ross 2017-01-12 11:43:35 -05:00
parent 41f476a863
commit 6048299a13
5 changed files with 16 additions and 12 deletions

View File

@ -48,7 +48,7 @@ var UI;
document.getElementById('noVNC_fallback_error') document.getElementById('noVNC_fallback_error')
.classList.add("noVNC_open"); .classList.add("noVNC_open");
document.getElementById('noVNC_fallback_errormsg').innerHTML = msg; document.getElementById('noVNC_fallback_errormsg').textContent = msg;
} catch (exc) { } catch (exc) {
document.write("noVNC encountered an error."); document.write("noVNC encountered an error.");
} }
@ -416,7 +416,7 @@ var UI;
switch (state) { switch (state) {
case 'connecting': case 'connecting':
document.getElementById("noVNC_transition_text").innerHTML = _("Connecting..."); document.getElementById("noVNC_transition_text").textContent = _("Connecting...");
document.documentElement.classList.add("noVNC_connecting"); document.documentElement.classList.add("noVNC_connecting");
break; break;
case 'connected': case 'connected':
@ -431,7 +431,7 @@ var UI;
break; break;
case 'disconnecting': case 'disconnecting':
UI.connected = false; UI.connected = false;
document.getElementById("noVNC_transition_text").innerHTML = _("Disconnecting..."); document.getElementById("noVNC_transition_text").textContent = _("Disconnecting...");
document.documentElement.classList.add("noVNC_disconnecting"); document.documentElement.classList.add("noVNC_disconnecting");
break; break;
case 'disconnected': case 'disconnected':
@ -531,7 +531,7 @@ var UI;
break; break;
} }
statusElem.innerHTML = text; statusElem.textContent = text;
statusElem.classList.add("noVNC_open"); statusElem.classList.add("noVNC_open");
// If no time was specified, show the status for 1.5 seconds // If no time was specified, show the status for 1.5 seconds

View File

@ -45,7 +45,7 @@
function message(str) { function message(str) {
console.log(str); console.log(str);
cell = document.getElementById('messages'); cell = document.getElementById('messages');
cell.innerHTML += msg_cnt + ": " + str + newline; cell.textContent += msg_cnt + ": " + str + newline;
cell.scrollTop = cell.scrollHeight; cell.scrollTop = cell.scrollHeight;
msg_cnt++; msg_cnt++;
} }

View File

@ -65,7 +65,7 @@
function msg(str) { function msg(str) {
console.log(str); console.log(str);
var cell = document.getElementById('messages'); var cell = document.getElementById('messages');
cell.innerHTML += str + "\n"; cell.textContent += str + "\n";
cell.scrollTop = cell.scrollHeight; cell.scrollTop = cell.scrollHeight;
} }
function dbgmsg(str) { function dbgmsg(str) {
@ -85,7 +85,7 @@
} }
notification = function (rfb, mesg, level, options) { notification = function (rfb, mesg, level, options) {
document.getElementById('VNC_status').innerHTML = mesg; document.getElementById('VNC_status').textContent = mesg;
} }
function do_test() { function do_test() {

View File

@ -49,7 +49,7 @@
function message(str) { function message(str) {
console.log(str); console.log(str);
var cell = document.getElementById('messages'); var cell = document.getElementById('messages');
cell.innerHTML += str + "\n"; cell.textContent += str + "\n";
cell.scrollTop = cell.scrollHeight; cell.scrollTop = cell.scrollHeight;
} }
@ -76,7 +76,7 @@
} }
notification = function (rfb, mesg, level, options) { notification = function (rfb, mesg, level, options) {
document.getElementById('VNC_status').innerHTML = mesg; document.getElementById('VNC_status').textContent = mesg;
} }
function start() { function start() {

View File

@ -111,10 +111,14 @@
var html; var html;
html = '<form onsubmit="return setPassword();"'; html = '<form onsubmit="return setPassword();"';
html += ' style="margin-bottom: 0px">'; html += ' style="margin-bottom: 0px">';
html += msg; html += '<label></label>'
html += '<input type=password size=10 id="password_input" class="noVNC_status">'; html += '<input type=password size=10 id="password_input" class="noVNC_status">';
html += '<\/form>'; html += '<\/form>';
status(html, "warn");
// bypass status() because it sets text content
document.getElementById('noVNC_status_bar').setAttribute("class", "noVNC_status_warn");
document.getElementById('noVNC_status').innerHTML = html;
document.getElementById('noVNC_status').querySelector('label').textContent = msg;
} }
function setPassword() { function setPassword() {
rfb.sendPassword(document.getElementById('password_input').value); rfb.sendPassword(document.getElementById('password_input').value);
@ -146,7 +150,7 @@
level = "warn"; level = "warn";
} }
document.getElementById('noVNC_status_bar').setAttribute("class", "noVNC_status_" + level); document.getElementById('noVNC_status_bar').setAttribute("class", "noVNC_status_" + level);
document.getElementById('noVNC_status').innerHTML = text; document.getElementById('noVNC_status').textContent = text;
} }
function updateState(rfb, state, oldstate) { function updateState(rfb, state, oldstate) {
var cad = document.getElementById('sendCtrlAltDelButton'); var cad = document.getElementById('sendCtrlAltDelButton');