Fix 7 frontend security vulnerabilities (4 critical, 3 high)
- Escape all innerHTML assignments with user/external data across 12 JS files - Upgrade credential encryption: per-value IV, key moved to sessionStorage - Fix open redirect in TOTP auth via proper URL hostname validation - Remove sensitive DNS topology data from localStorage cache - Add security regression test suite (51 tests) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -284,7 +284,7 @@
|
||||
const header = document.createElement('div');
|
||||
header.className = 'app-category-header';
|
||||
const categoryInfo = apiCategories?.[category] || {};
|
||||
header.innerHTML = `${categoryInfo.icon || ''} ${category}`;
|
||||
header.innerHTML = `${escapeHtml(categoryInfo.icon || '')} ${escapeHtml(category)}`;
|
||||
if (categoryInfo.color) {
|
||||
header.style.borderBottomColor = categoryInfo.color;
|
||||
}
|
||||
@@ -310,7 +310,7 @@
|
||||
}20; color: ${
|
||||
app.difficulty === 'Easy' ? '#2ecc71' :
|
||||
app.difficulty === 'Intermediate' ? '#f39c12' : '#e74c3c'
|
||||
};">${app.difficulty}</div>` : '';
|
||||
};">${escapeHtml(app.difficulty)}</div>` : '';
|
||||
|
||||
option.innerHTML = `
|
||||
<div class="app-option-icon">${escapeHtml(app.icon || '📦')}</div>
|
||||
@@ -488,7 +488,7 @@
|
||||
btn.type = 'button';
|
||||
const isSelected = autoPaths.includes(mount.hostPath);
|
||||
btn.style.cssText = `padding: 8px 14px; font-size: 0.85rem; background: color-mix(in srgb, var(--success) ${isSelected ? '40%' : '15%'}, var(--card-bg)); border: 1px solid var(--success); border-radius: 6px; cursor: pointer; color: var(--fg);`;
|
||||
btn.innerHTML = `<span style="font-weight: 500;">${mount.folderName}</span><br><span style="font-size: 0.7rem; color: var(--muted);">from ${mount.sourceImage}</span>`;
|
||||
btn.innerHTML = `<span style="font-weight: 500;">${escapeHtml(mount.folderName)}</span><br><span style="font-size: 0.7rem; color: var(--muted);">from ${escapeHtml(mount.sourceImage)}</span>`;
|
||||
btn.title = `${mount.hostPath} (from ${mount.sourceContainer})`;
|
||||
btn.onclick = () => {
|
||||
const currentPaths = mediaPathInput.value.split(',').map(p => p.trim()).filter(p => p);
|
||||
|
||||
Reference in New Issue
Block a user