diff --git a/examples/device/webusb_serial/website/application.js b/examples/device/webusb_serial/website/application.js
index a6bb3f890..5e9dbf471 100644
--- a/examples/device/webusb_serial/website/application.js
+++ b/examples/device/webusb_serial/website/application.js
@@ -34,6 +34,17 @@
const THEME_STATES = ['auto', 'light', 'dark'];
+ /// https://stackoverflow.com/a/6234804/4479969
+ const escapeHtml = unsafe => {
+ if (typeof unsafe !== 'string') unsafe = String(unsafe);
+ return unsafe
+ .replaceAll("&", "&")
+ .replaceAll("<", "<")
+ .replaceAll(">", ">")
+ .replaceAll('"', """)
+ .replaceAll("'", "'");
+ };
+
class CommandHistoryEntry {
constructor(text) {
this.text = text;
@@ -211,9 +222,9 @@
commandHistoryEntryBtn.type = 'button';
let time_str = new Date(commandHistoryEntry.time).toLocaleString();
commandHistoryEntryBtn.innerHTML = `
- ${time_str}
- ${commandHistoryEntry.text}
- ×${commandHistoryEntry.count}
+ ${escapeHtml(time_str)}
+ ${escapeHtml(commandHistoryEntry.text)}
+ ×${escapeHtml(commandHistoryEntry.count)}
`;
commandHistoryEntryBtn.addEventListener('click', () => {
if (uiCommandLineInput.disabled) return;
@@ -247,7 +258,7 @@
clearCommandHistory() {
this.commandHistory = [];
- uiCommandHistoryScrollbox.innerHTML = '';
+ uiCommandHistoryScrollbox.textContent = '';
localStorage.removeItem('commandHistory');
this.setStatus('Command history cleared', 'info');
}
@@ -322,8 +333,8 @@
let receivedDataEntryBtn = document.createElement('div');
receivedDataEntryBtn.className = 'received-data-entry';
receivedDataEntryBtn.innerHTML = `
- ${new Date(entry.time).toLocaleString()}
- ${entry.text}
+ ${escapeHtml(new Date(entry.time).toLocaleString())}
+ ${escapeHtml(entry.text)}
`;
documentFragment.appendChild(receivedDataEntryBtn);
}
@@ -352,7 +363,7 @@
clearReceivedData() {
this.receivedData = [];
- uiReceivedDataScrollbox.innerHTML = '';
+ uiReceivedDataScrollbox.textContent = '';
localStorage.removeItem('receivedData');
this.setStatus('Received data cleared', 'info');
}