Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5db55fd

Browse files
committed
security: Fix XSS vulnerabilities in UI components
- Replace innerHTML with textContent and createElement - Use safe DOM manipulation methods - Prevents XSS attacks through user-controlled data
1 parent f9d125d commit 5db55fd

3 files changed

Lines changed: 76 additions & 34 deletions

File tree

ui/components/DashboardTab.js

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,18 @@ export class DashboardTab {
103103
Object.entries(features).forEach(([feature, enabled]) => {
104104
const featureElement = document.createElement('div');
105105
featureElement.className = `feature-item ${enabled ? 'enabled' : 'disabled'}`;
106-
featureElement.innerHTML = `
107-
<span class="feature-name">${this.formatFeatureName(feature)}</span>
108-
<span class="feature-status">${enabled ? '✓' : '✗'}</span>
109-
`;
106+
107+
// Use textContent instead of innerHTML to prevent XSS
108+
const featureNameSpan = document.createElement('span');
109+
featureNameSpan.className = 'feature-name';
110+
featureNameSpan.textContent = this.formatFeatureName(feature);
111+
112+
const featureStatusSpan = document.createElement('span');
113+
featureStatusSpan.className = 'feature-status';
114+
featureStatusSpan.textContent = enabled ? '✓' : '✗';
115+
116+
featureElement.appendChild(featureNameSpan);
117+
featureElement.appendChild(featureStatusSpan);
110118
featuresContainer.appendChild(featureElement);
111119
});
112120
}
@@ -296,10 +304,18 @@ export class DashboardTab {
296304
['zone_1', 'zone_2', 'zone_3', 'zone_4'].forEach(zoneId => {
297305
const zoneElement = document.createElement('div');
298306
zoneElement.className = 'zone-item';
299-
zoneElement.innerHTML = `
300-
<span class="zone-name">${zoneId}</span>
301-
<span class="zone-count">undefined</span>
302-
`;
307+
308+
// Use textContent instead of innerHTML to prevent XSS
309+
const zoneNameSpan = document.createElement('span');
310+
zoneNameSpan.className = 'zone-name';
311+
zoneNameSpan.textContent = zoneId;
312+
313+
const zoneCountSpan = document.createElement('span');
314+
zoneCountSpan.className = 'zone-count';
315+
zoneCountSpan.textContent = 'undefined';
316+
317+
zoneElement.appendChild(zoneNameSpan);
318+
zoneElement.appendChild(zoneCountSpan);
303319
zonesContainer.appendChild(zoneElement);
304320
});
305321
return;
@@ -309,10 +325,18 @@ export class DashboardTab {
309325
const zoneElement = document.createElement('div');
310326
zoneElement.className = 'zone-item';
311327
const count = typeof data === 'object' ? (data.person_count || data.count || 0) : data;
312-
zoneElement.innerHTML = `
313-
<span class="zone-name">${zoneId}</span>
314-
<span class="zone-count">${count}</span>
315-
`;
328+
329+
// Use textContent instead of innerHTML to prevent XSS
330+
const zoneNameSpan = document.createElement('span');
331+
zoneNameSpan.className = 'zone-name';
332+
zoneNameSpan.textContent = zoneId;
333+
334+
const zoneCountSpan = document.createElement('span');
335+
zoneCountSpan.className = 'zone-count';
336+
zoneCountSpan.textContent = String(count);
337+
338+
zoneElement.appendChild(zoneNameSpan);
339+
zoneElement.appendChild(zoneCountSpan);
316340
zonesContainer.appendChild(zoneElement);
317341
});
318342
}

ui/components/HardwareTab.js

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,29 @@ export class HardwareTab {
107107
const txActive = activeAntennas.filter(a => a.classList.contains('tx')).length;
108108
const rxActive = activeAntennas.filter(a => a.classList.contains('rx')).length;
109109

110-
arrayStatus.innerHTML = `
111-
<div class="array-info">
112-
<span class="info-label">Active TX:</span>
113-
<span class="info-value">${txActive}/3</span>
114-
</div>
115-
<div class="array-info">
116-
<span class="info-label">Active RX:</span>
117-
<span class="info-value">${rxActive}/6</span>
118-
</div>
119-
<div class="array-info">
120-
<span class="info-label">Signal Quality:</span>
121-
<span class="info-value">${this.calculateSignalQuality(txActive, rxActive)}%</span>
122-
</div>
123-
`;
110+
// Clear and rebuild using safe DOM methods to prevent XSS
111+
arrayStatus.innerHTML = '';
112+
113+
const createInfoDiv = (label, value) => {
114+
const div = document.createElement('div');
115+
div.className = 'array-info';
116+
117+
const labelSpan = document.createElement('span');
118+
labelSpan.className = 'info-label';
119+
labelSpan.textContent = label;
120+
121+
const valueSpan = document.createElement('span');
122+
valueSpan.className = 'info-value';
123+
valueSpan.textContent = value;
124+
125+
div.appendChild(labelSpan);
126+
div.appendChild(valueSpan);
127+
return div;
128+
};
129+
130+
arrayStatus.appendChild(createInfoDiv('Active TX:', `${txActive}/3`));
131+
arrayStatus.appendChild(createInfoDiv('Active RX:', `${rxActive}/6`));
132+
arrayStatus.appendChild(createInfoDiv('Signal Quality:', `${this.calculateSignalQuality(txActive, rxActive)}%`));
124133
}
125134

126135
// Calculate signal quality based on active antennas

ui/components/PoseDetectionCanvas.js

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -539,14 +539,23 @@ export class PoseDetectionCanvas {
539539
const persons = this.state.lastPoseData?.persons?.length || 0;
540540
const zones = Object.keys(this.state.lastPoseData?.zone_summary || {}).length;
541541

542-
statsEl.innerHTML = `
543-
Connection: ${this.state.connectionState}<br>
544-
Frames: ${this.state.frameCount}<br>
545-
FPS: ${fps.toFixed(1)}<br>
546-
Persons: ${persons}<br>
547-
Zones: ${zones}<br>
548-
Uptime: ${uptime}s
549-
`;
542+
// Use textContent instead of innerHTML to prevent XSS
543+
statsEl.textContent = '';
544+
const lines = [
545+
`Connection: ${this.state.connectionState}`,
546+
`Frames: ${this.state.frameCount}`,
547+
`FPS: ${fps.toFixed(1)}`,
548+
`Persons: ${persons}`,
549+
`Zones: ${zones}`,
550+
`Uptime: ${uptime}s`
551+
];
552+
lines.forEach((line, index) => {
553+
if (index > 0) {
554+
statsEl.appendChild(document.createElement('br'));
555+
}
556+
const textNode = document.createTextNode(line);
557+
statsEl.appendChild(textNode);
558+
});
550559
}
551560

552561
showError(message) {

0 commit comments

Comments
 (0)