Skip to content

Commit 4c32a5d

Browse files
committed
sanitize user input when passing it to innerHTML in the UI
* use dompurify library for that * replaced many `innerHTML` assignments with `textContent` Signed-off-by: Thomas Jäckle <[email protected]>
1 parent fbcdcf8 commit 4c32a5d

24 files changed

+101
-107
lines changed

ui/modules/connections/connections.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/* eslint-disable require-jsdoc */
1717
import * as API from '../api.js';
1818
import * as Utils from '../utils.js';
19-
import {TabHandler} from '../utils/tabHandler.js';
19+
import { TabHandler } from '../utils/tabHandler.js';
2020
import connectionsHTML from './connections.html';
2121

2222
const observers = [];
@@ -57,7 +57,7 @@ export function setConnection(connection, isNewConnection = false) {
5757
}
5858

5959
export function loadConnections() {
60-
dom.tbodyConnections.innerHTML = '';
60+
dom.tbodyConnections.textContent = '';
6161
let connectionSelected = false;
6262
API.callConnectionsAPI('listConnections', (connections) => {
6363
connections.forEach((connection) => {
@@ -66,15 +66,15 @@ export function loadConnections() {
6666
row.id = id;
6767
if (API.env() === 'ditto_2') {
6868
API.callConnectionsAPI('retrieveConnection', (dittoConnection) => {
69-
row.insertCell(0).innerHTML = dittoConnection.name;
69+
row.insertCell(0).textContent = dittoConnection.name;
7070
},
7171
id);
7272
} else {
73-
row.insertCell(0).innerHTML = connection.name ? connection.name : id;
73+
row.insertCell(0).textContent = connection.name ? connection.name : id;
7474
}
7575
API.callConnectionsAPI('retrieveStatus', (status) => {
76-
row.insertCell(-1).innerHTML = status.liveStatus;
77-
row.insertCell(-1).innerHTML = status.recoveryStatus;
76+
row.insertCell(-1).textContent = status.liveStatus;
77+
row.insertCell(-1).textContent = status.recoveryStatus;
7878
},
7979
id);
8080
if (id === selectedConnectionId) {

ui/modules/connections/connectionsMonitor.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@
1010
*
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
13-
import {JSONPath} from 'jsonpath-plus';
14-
1513
import * as API from '../api.js';
1614
import * as Utils from '../utils.js';
17-
import * as Connections from './connections.js';
18-
import { TableFilter } from '../utils/tableFilter.js';
1915
import { FilterType, Term } from '../utils/basicFilters.js';
16+
import { TableFilter } from '../utils/tableFilter.js';
17+
import * as Connections from './connections.js';
2018
/* eslint-disable prefer-const */
2119
/* eslint-disable max-len */
2220
/* eslint-disable no-invalid-this */
@@ -112,7 +110,7 @@ function onEnableConnectionLogsClick() {
112110

113111
function retrieveConnectionMetrics() {
114112
Utils.assert(selectedConnectionId, 'Please select a connection', dom.tableValidationConnections);
115-
dom.tbodyConnectionMetrics.innerHTML = '';
113+
dom.tbodyConnectionMetrics.textContent = '';
116114
API.callConnectionsAPI('retrieveConnectionMetrics', (response) => {
117115
if (response.connectionMetrics) {
118116
Object.keys(response.connectionMetrics).forEach((direction) => {
@@ -154,7 +152,7 @@ function retrieveConnectionLogs() {
154152
}
155153

156154
function fillConnectionLogsTable() {
157-
dom.tbodyConnectionLogs.innerHTML = '';
155+
dom.tbodyConnectionLogs.textContent = '';
158156
connectionLogDetail.setValue('');
159157

160158
filteredLogs = dom.tableFilterConnectionLogs.filterItems(connectionLogs);
@@ -188,8 +186,8 @@ function onConnectionChange(connection, isNewConnection = true) {
188186
selectedConnectionId = connection ? connection.id : null;
189187
connectionStatusDetail.setValue('');
190188
connectionLogDetail.setValue('');
191-
dom.tbodyConnectionMetrics.innerHTML = '';
192-
dom.tbodyConnectionLogs.innerHTML = '';
189+
dom.tbodyConnectionMetrics.textContent = '';
190+
dom.tbodyConnectionLogs.textContent = '';
193191
if (!isNewConnection && connection && connection.id) {
194192
retrieveConnectionLogs();
195193
}

ui/modules/environments/environments.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
1313

14+
import * as Utils from '../utils.js';
1415
/* eslint-disable arrow-parens */
1516
/* eslint-disable prefer-const */
1617
/* eslint-disable require-jsdoc */
1718
import * as Authorization from './authorization.js';
18-
import * as Utils from '../utils.js';
19-
import defaultTemplates from './environmentTemplates.json';
2019
import environmentsHTML from './environments.html';
20+
import defaultTemplates from './environmentTemplates.json';
2121

2222

2323
const URL_PRIMARY_ENVIRONMENT_NAME = 'primaryEnvironmentName';
@@ -222,7 +222,7 @@ export function environmentsJsonChanged(modifiedField = null) {
222222
}
223223

224224
function updateEnvTable() {
225-
dom.tbodyEnvironments.innerHTML = '';
225+
dom.tbodyEnvironments.textContent = '';
226226
Object.keys(environments).forEach((key) => {
227227
Utils.addTableRow(dom.tbodyEnvironments, key, key === selectedEnvName);
228228
});

ui/modules/operations/piggyback.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
/* eslint-disable require-jsdoc */
1717
import * as API from '../api.js';
1818
import * as Utils from '../utils.js';
19+
import { TabHandler } from '../utils/tabHandler.js';
1920
import piggybackHTML from './piggyback.html';
2021
import piggybackPlaceholders from './piggybackPlaceholders.json';
2122
import * as Templates from './templates.js';
22-
import {TabHandler} from '../utils/tabHandler.js';
2323

2424
const EDITOR_INVALID_JSON_MNSSAGE = 'Invalid json!'
2525
const HEADER_IS_REQUIRED_MESSAGE = 'Headers field is required!';
@@ -205,7 +205,7 @@ function hasEditorError(editorSession) {
205205

206206
async function submitPiggybackCommand() {
207207
if (isCommandValid()) {
208-
dom.responseStatus.innerHTML = REQUEST_IN_PROGRESS_MESSAGE;
208+
dom.responseStatus.textContent = REQUEST_IN_PROGRESS_MESSAGE;
209209
aceResponse.setValue('', -1);
210210
let path = buildPath(
211211
dom.serviceSelector.value,
@@ -228,19 +228,19 @@ async function submitPiggybackCommand() {
228228
} catch (err) {
229229
onRequestDone();
230230
aceResponse.setValue(err.message, -1);
231-
dom.responseStatus.innerHTML = REQUEST_ERROR_MESSAGE;
231+
dom.responseStatus.textContent = REQUEST_ERROR_MESSAGE;
232232
}
233233
});
234234
promise.then((result: any) => {
235235
onRequestDone();
236236
result.json().then(resultJson => {
237237
aceResponse.setValue(Utils.stringifyPretty(resultJson), -1);
238-
dom.responseStatus.innerHTML = result.status;
238+
dom.responseStatus.textContent = result.status;
239239
});
240240
}).catch(err => {
241241
onRequestDone();
242242
aceResponse.setValue(err.message, -1);
243-
dom.responseStatus.innerHTML = REQUEST_ERROR_MESSAGE;
243+
dom.responseStatus.textContent = REQUEST_ERROR_MESSAGE;
244244
});
245245

246246
}

ui/modules/operations/servicesLogging.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/* eslint-disable require-jsdoc */
1717
import * as API from '../api.js';
1818
import * as Utils from '../utils.js';
19-
import {TabHandler} from '../utils/tabHandler.js';
19+
import { TabHandler } from '../utils/tabHandler.js';
2020
import servicesLoggingHTML from './servicesLogging.html';
2121

2222
let dom = {
@@ -47,12 +47,12 @@ function loadAllLogLevels() {
4747
API.callDittoREST('GET', '/devops/logging', null, null, false, true)
4848
.then((result) => createLoggerView(result))
4949
.catch((error) => {
50-
dom.divLoggers.innerHTML = '';
50+
dom.divLoggers.textContent = '';
5151
});
5252
}
5353

5454
function createLoggerView(allLogLevels) {
55-
dom.divLoggers.innerHTML = '';
55+
dom.divLoggers.textContent = '';
5656

5757
type LogLevel = {
5858
loggerConfigs?: object[]

ui/modules/operations/templates.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
1313
import * as Utils from '../utils.js';
14-
import templatesHTML from './templates.html';
15-
import templatesByService from './piggybackTemplates.json';
1614
import * as Piggyback from './piggyback.js';
15+
import templatesByService from './piggybackTemplates.json';
16+
import templatesHTML from './templates.html';
1717

1818
const dom = {
1919
templateServiceSelector: null,
@@ -88,9 +88,9 @@ function onTemplateSelected() {
8888
if (selectedTemplate) {
8989
let templateBody = buildPiggybackCommand(selectedTemplate.targetActorSelection,
9090
selectedTemplate.headers, selectedTemplate.command);
91-
dom.commandPreview.innerHTML = Utils.stringifyPretty(templateBody);
91+
dom.commandPreview.textContent = Utils.stringifyPretty(templateBody);
9292
} else {
93-
dom.commandPreview.innerHTML = "";
93+
dom.commandPreview.textContent = '';
9494
}
9595
}
9696

ui/modules/policies/policies.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ function onThingChanged(thing) {
111111
}
112112

113113
function refreshWhoAmI() {
114-
dom.tbodyWhoami.innerHTML = '';
114+
dom.tbodyWhoami.textContent = '';
115115
API.callDittoREST('GET', '/whoami')
116116
.then((whoamiResult) => {
117117
whoamiResult.subjects.forEach((subject) => {
@@ -166,7 +166,7 @@ export function updateRecentPolicies(policyId: String) {
166166

167167
function onEnvironmentChanged(modifiedField: String) {
168168
Environments.current()['recentPolicyIds'] = Environments.current()['recentPolicyIds'] || [];
169-
dom.tbodyRecentPolicies.innerHTML = '';
169+
dom.tbodyRecentPolicies.textContent = '';
170170
Environments.current().recentPolicyIds.forEach(entry => {
171171
Utils.addTableRow(dom.tbodyRecentPolicies, entry, thePolicy && thePolicy.policyId === entry, entry);
172172
});

ui/modules/policies/policiesEntries.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
1313

14-
import * as Utils from '../utils.js';
1514
import * as API from '../api.js';
16-
import { Observable } from '../utils/observable.js';
15+
import * as Utils from '../utils.js';
1716
import { CrudOperation, CrudToolbar } from '../utils/crudToolbar.js';
17+
import { Observable } from '../utils/observable.js';
1818
import * as Policies from './policies.js';
1919

2020
export let observable = Observable();
@@ -101,7 +101,7 @@ function putOrDeletePolicyEntry(entry, value, onSuccess) {
101101
};
102102

103103
function onPolicyChanged(policy: Policies.Policy) {
104-
dom.tbodyPolicyEntries.innerHTML = '';
104+
dom.tbodyPolicyEntries.textContent = '';
105105
dom.crudEntry.idValue = null;
106106
dom.crudEntry.editDisabled = (policy === null);
107107

ui/modules/policies/policiesImports.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
1313

14-
import * as ace from 'ace-builds/src-noconflict/ace';
15-
import * as Utils from '../utils.js';
1614
import * as API from '../api.js';
17-
import * as Policies from './policies.js';
18-
import * as PolicyEntries from './policiesEntries.js';
15+
import * as Utils from '../utils.js';
1916
import { CrudOperation, CrudToolbar } from '../utils/crudToolbar.js';
17+
import * as Policies from './policies.js';
2018

2119

2220
let selectedImport: string;
@@ -111,7 +109,7 @@ function setExplicitCheckboxesDisabledState(disabled: boolean) {
111109
}
112110

113111
function onPolicyChanged(policy: Policies.Policy) {
114-
dom.tbodyPolicyImports.innerHTML = '';
112+
dom.tbodyPolicyImports.textContent = '';
115113
dom.crudImport.idValue = null;
116114
dom.crudImport.editDisabled = (policy === null);
117115

@@ -145,7 +143,7 @@ function onPolicyChanged(policy: Policies.Policy) {
145143
async function setImport(importedPolicyId: string) {
146144

147145
dom.crudImport.idValue = importedPolicyId;
148-
dom.tbodyPolicyImportEntries.innerHTML = '';
146+
dom.tbodyPolicyImportEntries.textContent = '';
149147

150148
if (importedPolicyId) {
151149
const importedPolicy: Policies.Policy = await API.callDittoREST('GET', '/policies/' + importedPolicyId)

ui/modules/policies/policiesResources.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
*/
1313

1414
import * as ace from 'ace-builds/src-noconflict/ace';
15-
import * as Utils from '../utils.js';
1615
import * as API from '../api.js';
16+
import * as Utils from '../utils.js';
17+
import { CrudOperation, CrudToolbar } from '../utils/crudToolbar.js';
1718
import * as Policies from './policies.js';
1819
import * as PolicyEntries from './policiesEntries.js';
1920
import resourceTemplates from './resourceTemplates.json';
20-
import { CrudOperation, CrudToolbar } from '../utils/crudToolbar.js';
2121

2222
let selectedResource: string;
2323

@@ -138,7 +138,7 @@ function onEditToggleResource(event: CustomEvent) {
138138
function onEntryChanged(entryLabel: string) {
139139
selectedResource = null;
140140

141-
dom.tbodyPolicyResources.innerHTML = '';
141+
dom.tbodyPolicyResources.textContent = '';
142142
dom.crudResource.idValue = null;
143143
resourceEditor.setValue('');
144144
dom.crudResource.editDisabled = (entryLabel === null);

ui/modules/policies/policiesSubjects.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
*/
1313

1414
import * as ace from 'ace-builds/src-noconflict/ace';
15-
import * as Utils from '../utils.js';
1615
import * as API from '../api.js';
16+
import * as Utils from '../utils.js';
17+
import { CrudOperation, CrudToolbar } from '../utils/crudToolbar.js';
1718
import * as Policies from './policies.js';
1819
import * as PolicyEntries from './policiesEntries.js';
19-
import { CrudOperation, CrudToolbar } from '../utils/crudToolbar.js';
2020

2121

2222
let selectedSubject: string;
@@ -121,7 +121,7 @@ function onEditToggleSubject(event: CustomEvent) {
121121
function onEntryChanged(entryLabel: string) {
122122
selectedSubject = null;
123123

124-
dom.tbodyPolicySubjects.innerHTML = '';
124+
dom.tbodyPolicySubjects.textContent = '';
125125
dom.crudSubject.idValue = null;
126126
dom.crudSubject.editDisabled = (entryLabel === null);
127127
subjectEditor.setValue('');

ui/modules/things/attributes.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ function refreshAttribute(thing, attributePath = null) {
120120
function onThingChanged(thing) {
121121
dom.crudAttribute.editDisabled = (thing === null);
122122

123-
dom.tbodyAttributes.innerHTML = '';
123+
dom.tbodyAttributes.textContent = '';
124124
let count = 0;
125125
let thingHasAttribute = false;
126126
if (thing && thing.attributes) {

ui/modules/things/featureMessages.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,12 @@ function clearAllFields() {
163163
dom.inputMessageTimeout.value = '10';
164164
acePayload.setValue('');
165165
aceResponse.setValue('');
166-
dom.ulMessageTemplates.innerHTML = '';
166+
dom.ulMessageTemplates.textContent = '';
167167
dom.buttonMessageSend.disabled = !theFeatureId || theFeatureId === '';
168168
}
169169

170170
function refillTemplates() {
171-
dom.ulMessageTemplates.innerHTML = '';
171+
dom.ulMessageTemplates.textContent = '';
172172
Utils.addDropDownEntry(dom.ulMessageTemplates, 'Saved message templates', true);
173173
if (theFeatureId && Environments.current().messageTemplates[theFeatureId]) {
174174
Utils.addDropDownEntries(

ui/modules/things/features.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ function refreshFeature(thing, featureId = null) {
219219
function onThingChanged(thing) {
220220
dom.crudFeature.editDisabled = (thing === null);
221221
// Update features table
222-
dom.tbodyFeatures.innerHTML = '';
222+
dom.tbodyFeatures.textContent = '';
223223
let count = 0;
224224
let thingHasFeature = false;
225225
if (thing && thing.features) {

ui/modules/things/fields.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
13-
import {Modal} from 'bootstrap';
13+
import { Modal } from 'bootstrap';
1414

1515
import * as Environments from '../environments/environments.js';
1616
import * as Utils from '../utils.js';
@@ -165,14 +165,14 @@ function onEnvironmentChanged() {
165165
* (Re-)Initializes the fieldlist in the UI
166166
*/
167167
function updateFieldList() {
168-
dom.fieldList.innerHTML = '';
168+
dom.fieldList.textContent = '';
169169
theFieldIndex = -1;
170170
Environments.current().fieldList.forEach((field, i) => {
171171
const fieldSelected = dom.fieldPath.value === field.path;
172172
const row = dom.fieldList.insertRow();
173173
Utils.addCheckboxToRow(row, i, field.active, false, toggleFieldActiveEventHandler);
174-
row.insertCell(-1).innerHTML = field.path;
175-
row.insertCell(-1).innerHTML = field['label'] ? field.label : null;
174+
row.insertCell(-1).textContent = field.path;
175+
row.insertCell(-1).textContent = field['label'] ? field.label : null;
176176
if (fieldSelected) {
177177
theFieldIndex = i;
178178
row.classList.add('table-active');

ui/modules/things/messagesIncoming.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ function onResetMessagesClick() {
113113
messages = [];
114114
filteredMessages = [];
115115
dom.badgeMessageIncomingCount.textContent = '';
116-
dom.tbodyMessagesIncoming.innerHTML = '';
116+
dom.tbodyMessagesIncoming.textContent = '';
117117
messageDetail.setValue('');
118118
}
119119

@@ -188,7 +188,7 @@ function createFilterOptions(thing?: any): [Term?] {
188188
}
189189

190190
function onMessageFilterChange(event: CustomEvent) {
191-
dom.tbodyMessagesIncoming.innerHTML = '';
191+
dom.tbodyMessagesIncoming.textContent = '';
192192
filteredMessages = dom.tableFilterMessagesIncoming.filterItems(messages);
193193
filteredMessages.forEach((entry) => addTableRow(entry));
194194
Utils.updateCounterBadge(dom.badgeMessageIncomingCount, messages, filteredMessages);

0 commit comments

Comments
 (0)