pkg, examples: Avoid assigning .innerHTML

Assigning user controlled data to innerHTML is an anti-pattern, which
sets off security scanners like semgrep. Avoid it for all cases that
just set plain text, and use `.textContent` instead.

This leaves static HTML in pkg/base1/test-locale.js (which is both
harmless and also okay) and setting the branding in pkg/static/login.js
(which sets off the alarm, but doesn't get untrusted data).
This commit is contained in:
Martin Pitt 2023-06-30 14:12:05 +02:00 committed by Jelle van der Waa
parent 52d9554a4d
commit c5411445d4
9 changed files with 30 additions and 30 deletions

View file

@ -15,33 +15,33 @@ function showJournal(unitName, filter_arg) {
return;
// reset previous output
output.innerHTML = "";
output.textContent = "";
const argv = ["journalctl", "--output=cat", "--unit", unitName, "--follow", "--lines=all", filter_arg];
showJournal.journalctl = cockpit.spawn(argv, { superuser: "require", err: "message" })
.stream(data => output.append(document.createTextNode(data)))
.catch(ex => { output.innerHTML = JSON.stringify(ex) });
.catch(ex => { output.textContent = JSON.stringify(ex) });
}
function update(process) {
state.innerHTML = cockpit.format("$0 $1", process.serviceName, process.state);
state.textContent = cockpit.format("$0 $1", process.serviceName, process.state);
switch (process.state) {
case ProcessState.INIT:
break;
case ProcessState.STOPPED:
run_button.removeAttribute("disabled");
run_button.innerHTML = "Start";
run_button.textContent = "Start";
break;
case ProcessState.RUNNING:
run_button.removeAttribute("disabled");
run_button.innerHTML = "Terminate";
run_button.textContent = "Terminate";
// StateChangeTimestamp property is in µs since epoch, but journalctl expects seconds
showJournal(process.serviceName, "--since=@" + Math.floor(process.startTimestamp / 1000000));
break;
case ProcessState.FAILED:
run_button.setAttribute("disabled", "");
run_button.innerHTML = "Start";
run_button.textContent = "Start";
// Show the whole journal of this boot
showJournal(process.serviceName, "--boot");
break;
@ -77,7 +77,7 @@ cockpit.transport.wait(() => {
else
process.run(["/bin/sh", "-ec", command.value])
.catch(ex => {
state.innerHTML = "Error: " + ex.toString();
state.textContent = "Error: " + ex.toString();
run_button.setAttribute("disabled", "");
});
});

View file

@ -10,18 +10,18 @@ function ping_run() {
.then(ping_success)
.catch(ping_fail);
result.innerHTML = "";
output.innerHTML = "";
result.textContent = "";
output.textContent = "";
}
function ping_success() {
result.style.color = "green";
result.innerHTML = "success";
result.textContent = "success";
}
function ping_fail() {
result.style.color = "red";
result.innerHTML = "fail";
result.textContent = "fail";
}
function ping_output(data) {

View file

@ -56,9 +56,9 @@ document.getElementById("get").addEventListener("click", () => {
xhr.onreadystatechange = () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
console.log("XMLHttpRequest to", url, "done with status", xhr.status, "text", xhr.responseText);
document.getElementById("result").innerHTML = xhr.status.toString();
document.getElementById("result").textContent = xhr.status.toString();
const output = document.getElementById("output");
output.innerHTML = "";
output.textContent = "";
output.append(document.createTextNode(xhr.responseText));
}
};

View file

@ -37,17 +37,17 @@
timedate.addEventListener("changed", display_zone);
function display_zone() {
current.innerHTML = timedate.Timezone;
current.textContent = timedate.Timezone;
}
function change_zone() {
timedate.SetTimezone(input.value, true)
.catch(change_fail);
failure.innerHTML = "";
failure.textContent = "";
}
function change_fail(err) {
failure.innerHTML = err.message;
failure.textContent = err.message;
}
</script>

View file

@ -9,7 +9,7 @@ function parent_window(assert) {
assert.expect(4);
window.assert = assert; // for the child frame
document.getElementById("qunit-header").innerHTML = "Cockpit Parent Frame";
document.getElementById("qunit-header").textContent = "Cockpit Parent Frame";
window.name = "cockpit1";
let initialized = false;
let frame;

View file

@ -7,7 +7,7 @@ function parent_window(assert) {
assert.expect(12);
window.assert = assert; // for the child frame
document.getElementById("qunit-header").innerHTML = "Cockpit Parent Frame";
document.getElementById("qunit-header").textContent = "Cockpit Parent Frame";
let count = 0;
let child_done = false;

View file

@ -9,7 +9,7 @@ function parent_window(assert) {
assert.expect(7);
window.assert = assert; // for the child frame
document.getElementById("qunit-header").innerHTML = "Cockpit Parent Frame";
document.getElementById("qunit-header").textContent = "Cockpit Parent Frame";
window.name = "cockpit1";
let initialized = false;
let frame;

View file

@ -16,10 +16,10 @@ let close_problem;
function update() {
const element = document.getElementById("speed");
if (channel || websocket) {
element.innerHTML = cockpit.format_bytes_per_sec((total * 1000) / (Date.now() - start));
element.textContent = cockpit.format_bytes_per_sec((total * 1000) / (Date.now() - start));
console.log(total);
} else {
element.innerHTML = "";
element.textContent = "";
}
const memory = document.getElementById("memory");
@ -28,11 +28,11 @@ function update() {
proc = cockpit.script("echo $PPID && cat /proc/$PPID/statm");
proc.then(function(data) {
const parts = data.split("\n");
pid.innerHTML = parts[0];
memory.innerHTML = parts[1];
pid.textContent = parts[0];
memory.textContent = parts[1];
proc = null;
}, function(ex) {
memory.innerHTML = String(ex);
memory.textContent = String(ex);
proc = null;
});
}
@ -200,7 +200,7 @@ function download(ev) {
function spawn() {
stop();
document.getElementById("spawn-result").innerHTML = "Running...";
document.getElementById("spawn-result").textContent = "Running...";
const command = document.getElementById("spawn-command").value;
start = Date.now();
@ -212,17 +212,17 @@ function spawn() {
channel.stream(data => {
console.log("spawn: stream block length", data.length);
total += data.length;
document.getElementById("spawn-output").innerHTML = data;
document.getElementById("spawn-output").textContent = data;
});
channel.then(() => {
console.log("spawn: command finished successfully");
stop();
document.getElementById("spawn-result").innerHTML = "success";
document.getElementById("spawn-result").textContent = "success";
});
channel.catch(ex => {
console.log("spawn: command failed", JSON.stringify(ex));
stop();
document.getElementById("spawn-result").innerHTML = `failed with exit code ${ex.exit_status}: ${ex.message}`;
document.getElementById("spawn-result").textContent = `failed with exit code ${ex.exit_status}: ${ex.message}`;
});
}

View file

@ -45,7 +45,7 @@ document.addEventListener("DOMContentLoaded", () => {
});
function update_nav() {
document.getElementById("nav").innerHTML = '';
document.getElementById("nav").textContent = '';
const path = ["top"].concat(cockpit.location.path);
const e_nav = document.getElementById("nav");
path.forEach((p, i) => {
@ -87,7 +87,7 @@ document.addEventListener("DOMContentLoaded", () => {
if (error)
return complain(error);
document.getElementById('file-content').textContent = normalize_counter(content).counter;
document.getElementById('file-error').innerHTML = "";
document.getElementById('file-error').textContent = "";
}
counter.watch(changed);